类型别名可以说是 TypeScript 类型编程中最重要的一个功能,从一个简单的函数类型别名,到让你眼花缭乱的类型体操,都离不开类型别名。虽然很重要,但它的使用却并不复杂:

    1. type A = string;

    我们通过 type 关键字声明了一个类型别名 A ,同时它的类型等价于 string 类型。类型别名的作用主要是对一组类型或一个特定类型结构进行封装,以便于在其它地方进行复用。
    比如抽离一组联合类型:

    1. type StatusCode = 200 | 301 | 400 | 500 | 502;
    2. type PossibleDataTypes = string | number | (() => unknown);
    3. const status: StatusCode = 502;

    抽离一个函数类型:

    1. type Handler = (e: Event) => void;
    2. const clickHandler: Handler = (e) => { };
    3. const moveHandler: Handler = (e) => { };
    4. const dragHandler: Handler = (e) => { };

    声明一个对象类型,就像接口那样:

    1. type ObjType = {
    2. name: string;
    3. age: number;
    4. }

    看起来类型别名真的非常简单,不就是声明了一个变量让类型声明更简洁和易于拆分吗?如果真的只是把它作为类型别名,用来进行特定类型的抽离封装,那的确很简单。然而,类型别名还能作为工具类型。工具类同样基于类型别名,只是多了个泛型
    如果你还不了解泛型也无需担心,现阶段我们只要了解它和类型别名相关的使用就可以了。至于更复杂的泛型使用场景,我们后面会详细了解。
    在类型别名中,类型别名可以这么声明自己能够接受泛型(我称之为泛型坑位)。一旦接受了泛型,我们就叫它工具类型:

    1. type Factory<T> = T | number | string;

    虽然现在类型别名摇身一变成了工具类型,但它的基本功能仍然是创建类型,只不过工具类型能够接受泛型参数,实现更灵活的类型创建功能。从这个角度看,工具类型就像一个函数一样,泛型是入参,内部逻辑基于入参进行某些操作,再返回一个新的类型。比如在上面这个工具类型中,我们就简单接受了一个泛型,然后把它作为联合类型的一个成员,返回了这个联合类型。

    1. const foo: Factory<boolean> = true;

    当然,我们一般不会直接使用工具类型来做类型标注,而是再度声明一个新的类型别名:

    1. type FactoryWithBool = Factory<boolean>;
    2. const foo: FactoryWithBool = true;

    同时,泛型参数的名称(上面的 T )也不是固定的。通常我们使用大写的 T / K / U / V / M / O …这种形式。如果为了可读性考虑,我们也可以写成大驼峰形式(即在驼峰命名的基础上,首字母也大写)的名称,比如:

    1. type Factory<NewType> = NewType | number | string;

    声明一个简单、有实际意义的工具类型:

    1. type MaybeNull<T> = T | null;

    这个工具类型会接受一个类型,并返回一个包括 null 的联合类型。这样一来,在实际使用时就可以确保你处理了可能为空值的属性读取与方法调用:

    1. type MaybeNull<T> = T | null;
    2. function process(input: MaybeNull<{ handler: () => {} }>) {
    3. input?.handler();
    4. }

    类似的还有 MaybePromise、MaybeArray。这也是我在日常开发中最常使用的一类工具类型:

    1. type MaybeArray<T> = T | T[];
    2. // 函数泛型我们会在后面了解~
    3. function ensureArray<T>(input: MaybeArray<T>): T[] {
    4. return Array.isArray(input) ? input : [input];
    5. }

    另外,类型别名中可以接受任意个泛型,以及为泛型指定约束、默认值等,这些内容我们都会在泛型一节深入了解。
    总之,对于工具类型来说,它的主要意义是基于传入的泛型进行各种类型操作,得到一个新的类型。而这个类型操作的指代就非常非常广泛了,甚至说类型编程的大半难度都在这儿呢,这也是这本小册占据篇幅最多的部分。