在类型工具学习中,我们已经接触过类型别名中的泛型,比如类型别名如果声明了泛型坑位,那其实就等价于一个接受参数的函数:
type Factory<T> = T | number | string;
上面这个类型别名的本质就是一个函数,T 就是它的变量,返回值则是一个包含 T 的联合类型,我们可以写段伪代码来加深一下记忆:
function Factory(typeArg){
return [typeArg, number, string]
}
类型别名中的泛型大多是用来进行工具类型封装,比如我们在上一节的映射类型中学习的工具类型:
type Stringify<T> = {
[K in keyof T]: string;
};
type Clone<T> = {
[K in keyof T]: T[K];
};
Stringify 会将一个对象类型的所有属性类型置为 string ,而 Clone 则会进行类型的完全复制。我们可以提前看一个 TypeScript 的内置工具类型实现:
type Partial<T> = {
[P in keyof T]?: T[P];
};
工具类型 Partial 会将传入的对象类型复制一份,但会额外添加一个?,还记得这代表什么吗?可选,也就是说现在我们获得了一个属性均为可选的山寨版:
interface IFoo {
prop1: string;
prop2: number;
prop3: boolean;
prop4: () => void;
}
type PartialIFoo = Partial<IFoo>;
// 等价于
interface PartialIFoo {
prop1?: string;
prop2?: number;
prop3?: boolean;
prop4?: () => void;
}
类型别名与泛型的结合中,除了映射类型、索引类型等类型工具以外,还有一个非常重要的工具:条件类型。我们先来简单了解一下:
type IsEqual<T> = T extends true ? 1 : 2;
type A = IsEqual<true>; // 1
type B = IsEqual<false>; // 2
type C = IsEqual<'linbudu'>; // 2
在条件类型参与的情况下,通常泛型会被作为条件类型中的判断条件(T extends Condition,或者 Type extends T)以及返回值(即 : 两端的值),这也是我们筛选类型需要依赖的能力之一。