泛型
以下内容摘抄自《TypeScript编程》Boris Cherny著 安道译
1. 函数类型
// 简写型 type Log = (message: string, userId?: string) => void; // 完整型 type Log = { (message: string, userId?: string): void };
2. 泛型
泛型参数是在类型层面施加约束的占位类型,也称多态类型参数。如下所示,T就像是一个占位类型,类型检查器将根据上下文填充具体的类型。T把Filter的类型参数化了,因此才称其为泛型参数,简称泛型。
尖括号的位置限定泛型的作用域(只有少数几个地方可以使用尖括号),TypeScript将确保当前作用域中相同的泛型参数最终都绑定同一个具体类型。鉴于这个示例中尖括号的位置他,TypeScript将在调用filter函数时为泛型T绑定具体类型。而为T绑定哪一个具体类型,取决于调用filter函数时传入的参数。在一对尖括号中可以声明任意个以逗号分隔的泛型参数。
// 类型声明 type Filter = { <T>(array: T[], f: (item: T) => boolean): T[] } // 函数声明 function filter<T>(array: T[], f: (item: T) => boolean): T[] { // ... } // JavaScript标准库中的接口 interface Array<T> { filter( callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any ): T[]; map<U>( callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any ): U[]; } // 多态(继承,即限制T为某种类型或其子类型) function mapNode<T extends TreeNode>( node: T, f: (value: string) => string ): T { return { ...node, value: f(node.value) } } // 泛型默认类型 type MyEvent<T extends HTMLElement = HTMLElement> = { target: T, type: string }
3. 泛型的使用场景
泛型让函数的功能更具一般性,比接受具体类型的函数更强大。《TypeScript编程》一书的作者建议只要可能就应该使用泛型,这样写出的代码更具一般性,可重复使用,并且简单扼要。JavaScript标准库中的很多函数都使用泛型,尤其是Array原型的方法。
个人理解,当函数、对象或接口中有不确定类型的参数时,1)如果不同参数类型之间存在关联,那么可以使用泛型,约束参数类型之间的关系;2)如果确定参数类型的所属范围,那么可以使用泛型extends约束参数类型