1、泛型
泛型,即能够创建一个可以在多种类型上而不是单一类型上工作的组件。这允许用户使用这些组件并使用他们自己的类型。
举个例子:
function identity(arg: number): number {
return arg;
}
我们定义的参数类型是number类型,返回类型也是number类型。那么如果想要参数还可以是string类型,以前我们是这么做的。
function identity(arg: any): any {
return arg;
}
使用any确实可以达到效果,但也是存在问题的。我们期望的是传入的参数跟返回的结果的类型是一致的。这里我们传入参数number类型,返回的可以是任何类型。丢失了返回的值的类型信息。
在这里,我们将使用类型变量,一种特殊的变量,它作用于类型而不是值。
// T 是一个类型的
function identity<T>(arg: T): T {
return arg;
}
let res = identity<string>("hello world") // string
// 简单的类型,可以直接被推导出来
let str = identity("hello world") // string
let num = identity<number>(1) // number
// 箭头函数
const f = <T>(arg: T) => T
function loggingIdentity<T>(arg: T): T {
// 这里会报错,因为arg不一定有length, 比如参数是number类型
console.log(arg.length);
return arg;
}
// T[] 等价于 Array<T>
function loggingIdentity<T>(arg: T[]): T {
// 改为T[],数组类型一定有length
console.log(arg.length);
return arg;
}
探讨函数本身的类型以及如何创建通用接口。
函数类型声明,myIdentity 的类型就是 <T>(arg: T) => T
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: <T>(arg: T) => T = identity
//也可以写成这种形式
let myIdentity: { <T>(arg: T): T } = identity
接口官方例子
// 定义一个接口,
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
泛型类
泛型类,在类名称后面加上<T>,约定类中某些属性或者方法使用的类型。官方案例:
class GenericNumber<NumType> {
zeroValue: NumType;
add: (x: NumType, y: NumType) => NumType;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x + y;
};
通用约束
之前的例子,我们要使用参数的length属性,可以约束下泛型必须具备length。
interface HasLength {
length: number;
}
function loggingIdentity<T extends HasLength>(arg: T): T {
console.log(arg.length);
return arg;
}
在通用约束中使用类型参数
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a");
getProperty(x, "m"); // 报错,m 不存在x的key 中
keyof会取出x中的所有的key的unino,结果为'a'|'b'|'c'|'d',m不存在。
使用类,作为类型
When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions.
译文:
当使用泛型在 TypeScript 中创建工厂时,必须通过类的构造函数引用类类型。
function create<Type>(c: { new (): Type }): Type {
return new c();
}