只是学习笔记。
遇到复杂的类型定义,就得用TypeScript 中的泛型了。
其实泛型可以说是类型的变量。从最简单的例子看起
function identity<T>(arg: T): T { return arg; }
这个函数只是想表达一下,输入啥类型就返回啥类型。然而输入类型可能有很多种,这时候就需要一个泛型,T是一个类型的变量。
function identity<T>(arg: T[]): T { return arg[1]; }
这个可以更直观看出T是个类型的变量,输入T类型的数组,输出其中一个元素。
调用时,可以给泛型传递类型。
identity<string>(['1']);
但没有必要,ts可以自动推导出类型。
identity(['1']);
当函数的类型比较复杂的时候可以定义一个泛型接口
interface GenericIdentityFn { <T>(arg: T): T; }
随后函数的返回类型就好说了
function identity<T>(arg: T): T { return arg; } let myIdentity: GenericIdentityFn = identity;
定义了泛型接口之后我们就可以规定具体可以传入哪些玩意了
给这个接口加个泛型
interface GenericIdentityFn<T> { (arg: T): T; }
这样T就从“实现此接口的函数的传入类型”变成了“实现接口时规定的类型”
const myIdentity: GenericIdentityFn<string | number> = (arg: string) => arg;
这里规定,实现这个接口的函数必须接收字符串或者数字。
赋值的这个函数接受的是字符串,所以类型检查通过。
还可以使用泛型来对传入参数进行更详细的限制。例如,我们只要求传入的这个参数拥有length类型,而不管是数组还是字符串还是类数组的玩意。
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; }
更进阶的,例如要做一个从object中取值的函数,我们想要key必须是这个object中存在,这样的需求竟然也可以实现。
function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "a"); // okay getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
https://zhongsp.gitbooks.io/typescript-handbook/content/doc/handbook/Generics.html