这是 TS2.8 版本中推出的特性,此能力让类型定义变的更加灵活,须要注意:extends 运用在 type 和 class 中时彻底是两种做用的效果。html
条件类型是一种条件表达式进行类型的关系检测。typescript
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
复制代码
能够简单理解为一个三元表达式,固然没有那么简单,让咱们更深的扒一扒。函数
首先理解什么是 ”可被分配“,例以下面的这个简单且正确的类型声明与进行赋值:post
const num: number = 1; // 可被分配
cosnt str: string = 2; // 不可被分配
复制代码
而条件类型的判断逻辑,和上面的的 ”可被分配“ 相同逻辑:ui
type isNum<T> = T extends number ? number : string
type Num = InstanceVal<1> // number;
type Str = InstanceVal<'1'> // string;
复制代码
就像 if
语句一个道理,能够无限嵌套。下面写一个:根据值类型,获取值类型名称的函数类型(这也是官方给的例子):spa
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 T0 = TypeName<string>; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName<true>; // "boolean"
type T3 = TypeName<() => void>; // "function"
type T4 = TypeName<string[]>; // "object"
复制代码
type A = 'x';
type B = 'x' | 'y';
type Y = A extends B ? true : false; // true
复制代码
其中联合类型 A 的全部子类型,在联合类型 B 中存在,则条件知足。 若是咱们把返回值替换为其余的类型定义,就能根据判断,得出想要的类型。code
咱们编写一个 函数类型,逻辑很简单:给的类型是 x 时返回 a 则返回 b。htm
type AB<T> = T extends 'x' ? 'a' : 'b';
type A = AB<'x'>;
// 获得 type A = 'a'
复制代码
看上去没什么问题,那是由于咱们传入了一个明确的判断值,确定为 true。ip
假设咱们传入不肯定的值,例如一个联合类型 'x' | 'y'
会怎么样呢?判断逻辑多是 true,也多是 false。其实 TypeScript 也不知道该怎么办,因而乎它就把两个结果的值都返回给咱们了:get
type AB<T> = T extends 'x' ? 'a' : 'b';
type All = AB<'x' | 'y'>; // 非肯定条件,多是 'x' 或 'y'
// 获得 type All = 'a' | 'b';
复制代码
咱们获得了一个 联合类型 包含全部返回值的。
官方的解释是:此时作了 推迟解析条件类型 的处理。
在得知 条件类型不肯定时会返回全部的值 的特性状况下,会产生一些额外的效果。
如今咱们把传入的 T
类型也一块儿返回,有趣的事情就发生了。且放置 T
位置不一样,产生的效果也不一样:
type Other = "a" | "b";
type Merge<T> = T extends "x" ? T : Other; // T 等于匹配的类型,而后加上 Other 联合类型一块儿返回
type Values = Merge<"x" | "y">;
// 获得 type Values = "x" | "a" | "b";
复制代码
type Other = "a" | "b";
type Merge<T> = T extends "x" ? Other : T; // T 等于除匹配类型的额外全部类型(官方叫候选类型)
type Values = Merge<"x" | "y">;
// 获得 type Values = "a" | "b" | 'y';
复制代码
经过这个特性,咱们能够写出 Diff<T, U>
这样经常使用的函数类型,一个过滤功能的函数类型:
type Filter<T, U> = T extends U ? never : T;
type Values = Filter<"x" | "y" | "z", "x">;
// 获得 type Values = "y" | "z"
复制代码
对于 never
将单独进行细讲,这里咱们理解为 什么都没有 就行。
使用条件类型结合 映射类型 又能够组合出不少函数类型,官网也所以预置了不少高级类型(例如:Typescript 中的 Partial, Readonly, Record, Pick),以后将会分享官方定义的全部高级类型。
条件类型还提供了 infer
推断的能力,单独进行讲解 《TypeScript 条件类型的 infer 类型推断能力》