泛型

以下内容摘抄自《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约束参数类型

posted @ 2023-05-14 21:29  黄燃  阅读(22)  评论(0编辑  收藏  举报