泛型
介绍
为了擦黄健一致的良好的API,组件在支持当前数据类型的基础上,还需要支持未来的数据类型
需求:创建一个函数接收一个参数,并将这个参数返回
对于这样的函数,如果对输入的参数类型使用any。那么就会丢失信息,即传入的类型与返回的类型是相同的。因此我们可以使用类型变量来解决这个问题,类型变量是一种特殊的变量,只用于表示类型而不是值。这样可以是我们追踪函数里的类型信息。
function identity<T>(arg:T):T{return arg;}
这个 identity函数叫做泛型。
let output=identity<string>("myString) // 方法1let output=indentity("myString)``// 方法2
其中第二种方法更加普遍,利用了类型推论。一般的编译器会查看myString的值,然后把T设置为他的类型。当然也存在编译器不能自动推断出类型的情况。这是只能使用方法1.
使用泛型变量
使用泛型变量,必须把传入的参数当作任意的类型。
理解loggingIdentity的类型:泛型函数loggingIdentity,接收类型参数T和参数arg,它是个元素类型是T的数组,并返回元素类型是T的数组。 如果我们传入数字数组,将返回一个数字数组,因为此时 T的的类型为number。 这可以让我们把泛型变量T当做类型的一部分使用,而不是整个类型,增加了灵活性。
function loggingIdentity<T>(arg: Array<T>): Array<T> {console.log(arg.length); // Array has a .length, so no more errorreturn arg;}
泛型类型
如何创建泛型接口
function identity<T>(arg: T): T {return arg}let myIdentity: <T>(arg: T) => T = identity;// 使用不同的泛型参数名let myIdentity2: <U>(arg: U) => U = identity;// 使用带有调用签名的对象字面量来定义泛型函数let myIdentity3: { <T>(arg: T): T } = identity;// 泛型接口interface GenericIdentityFn {<T>(arg: T): T}let myIdentity4: GenericIdentityFn = identity;// 把泛型参数当成接口的参数interface GenericIdentityFn2<T> {(arg: T): T;}let myIdentity5: GenericIdentityFn2<number> = identity;
泛型类
泛型类使用(<>)括起泛型类型,跟在类名后面。泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
class GenericNumber<T> {zeroValue: T;add: (x: T, y: T) => T}let myGenericNumber = new GenericNumber<number>();myGenericNumber.zeroValue = 0;myGenericNumber.add = function (x, y) {return x + y;};let stringNumeric = new GenericNumber<string>();stringNumeric.zeroValue = '0';myGenericNumber.add = function (x, y) {return x + y;};console.log(stringNumeric.add(stringNumeric.zeroValue, 'test'))
泛型约束
限制函数去处理任意带有length属性的所有类型。只要类型传入有这个属性就允许。增加泛型约束后,则必须传入符合约束的类型的值
interface Lengthwise {length: number;}function loggingIdentity<T extends Lengthwise>(arg:T):T {console.log(arg.length);return arg}
泛型约束中使用类型参数
需求:确保属性在某个对象上。
function getProperty(obj: T, key: K) {return obj[key];}let x = {a: 1, b: 2, c: 3, d: 4};getProperty(x, "a");
在泛型里使用类类型
在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型。比如,
function create<T>(c: { new(): T }): T {return new c();}
使用原型属性推断并约束构造函数与类实例的关系
class BeeKeeper {hasMask: boolean}class ZooKeeper {nameTag: string;}class Animal {numLegs: number;}class Bee extends Animal {keeper: BeeKeeper;}class Lion extends Animal {keeper: ZooKeeper;}function createInstance<A extends Animal>(c: new() => A): A {return new c();}createInstance(Lion).keeper.nameTag; //typeCheckscreateInstance(Bee).keeper.hasMask; //typeChecksa
