TypeScript 的 extends 条件类型

这是 TS2.8 版本中推出的特性,此能力让类型定义变的更加灵活,需要注意:extends 运用在 type 和 class 中时完全是两种作用的效果。

条件类型是一种 条件表达式 进行类型的关系检测

分为以下几种类型检测

  1. 简单值(原始值)的匹配

    1
    2
    3
    4
    5
    6
    相当于是匹配两值是否相等
    type Equal<X, Y> = X extends Y ? true : false;

    type Num = Equal<1, 1>; // true
    type Str = Equal<'a', 'a'>; // true
    type Boo = Equal<true, false>; // false
  2. 简单的类型匹配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    匹配是否属于某个基本类型
    type isStr<T> = T extends string ? true : false;
    isStr<"2"> // true
    isStr<2> // false

    当然,我们也可以像写三元表达式一样进行类型匹配
    type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";

    type A = TypeName<"a">; // "string"
    type B = TypeName<true>; // "boolean"
    type C = TypeName<() => void>; // "function"
    type D = TypeName<string[]>; // "object"
  3. 判断联合类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    type A<A, B> = A extends B ? 'true' : 'false'; // 'true'

    type B = 'x';
    type C = 'x' | 'y';

    type D = A<B, C> // 'true'
    看上去没什么问题,那是因为我们传入了一个明确的判断值,肯定为 'true'
    但是当传入的A是联合类型的话,返回的值则大径相庭
    type B = 'x' | 'y';
    type C = 'x' | 'y';
    type D = A<B, C> // 'true' 当两个联合一样返回是'true'

    type B = 'x' | 'y' | 'z';
    type C = 'x' | 'y';
    type D = A<B, C> // 'true' | 'false' 两个联合类型不一样时,返回的是 'true'|'false'

    其实是因为Ts的一个 *分布条件类型* 特性, T extends U ? X : Y,当 T 是 A|B 时候,会拆分为A extends U ? X : Y | B extends U ? X : Y。
    上面被转换为:'x' extends C ? 'true' : 'false' | 'y' extends C ? 'true' : 'false' | 'z' extends C ? 'true' : 'false' ==> 'true' | 'true' | 'false' ==> 'true' | 'false'

    通过这个特性,我们可以实现Exclude过滤功能的函数:
    type Exclude<T, U> = T extends U ? never : T;

    type Values = Exclude<"x" | "y" | "z", "x">; // 'y' | 'z'

最后更新: 2021年02月08日 19:08

原始链接: https://xmtd.github.io/2020/12/24/ts-extends-md/

× 请我吃糖~
打赏二维码