编写可复用的函数和类型,在每次调用时都完整保留类型的精确性。
在 Kodokon 中打开本课你其实已经在不知不觉中使用泛型了:string[]、Promise<number>……是时候编写你自己的泛型了。泛型引入了一个类型参数,一个在每次使用时被替换为具体类型的变量。目标是:逻辑只写一次,而不牺牲类型的精确性。
function first<T>(items: T[]): T | undefined {
return items[0];
}
const n = first([10, 20, 30]);
const s = first(["a", "b"]);注意你在调用处没有指定任何东西:TypeScript 从实参中推断出了 T。一个不加约束的泛型可以接受任何东西;然而函数往往需要对其数据有最起码的保证。extends 关键字为 T 施加了一个最小形状。
interface HasId {
id: number;
}
function findById<T extends HasId>(
items: T[],
id: number
): T | undefined {
return items.find((item) => item.id === id);
}类型本身也可以是泛型的。这在网络代码中是家常便饭:响应的结构是稳定的,只有 data 的内容会变化。于是单一的一个类型就能描述你所有的 API 响应。
interface ApiResponse<T> {
ok: boolean;
data: T;
}
type UserResponse = ApiResponse<{ name: string }>;
const res: UserResponse = {
ok: true,
data: { name: "Ada" },
};