条件类型
Typescript 2.8
条件类型
TypeScript2.8引入了条件类型,它能够表示非统一的类型。有条件的类型会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一:
T extends U ? X : Y
1
上面的类型意思是,若T能够赋值给U,那么类型是X,否则为Y。
# 条件类型
有条件的类型T extends U ? X : Y或者解析为X,或者解析为Y,再或者延迟解析,因为它可能依赖一个或多个类型变量。是否直接解析或推迟取决于:
- 首先,令
T'和U'分别为T和U的实例,并将所有类型参数替换为any,如果T'不能赋值给U',则将有条件的类型解析成Y。直观上讲,如果最宽泛的T的实例不能赋值给最宽泛的U的实例,那么我们就可以断定不存在可以赋值的实例,因此可以解析为Y。 - 其次,针对每个在
U内由推断声明引入的类型变量,依据从T推断到U来收集一组候选类型(使用与泛型函数类型推断相同的推断算法)。对于给定的推断类型变量V,如果有候选类型是从协变的位置上推断出来的,那么V的类型是那些候选类型的联合。反之,如果有候选类型是从逆变的位置上推断出来的,那么V的类型是那些候选类型的交叉类型。否则V的类型是never。 - 然后,令
T''为T的一个实例,所有推断的类型变量用上一步的推断结果替换,如果T''明显可赋值给U,那么将有条件的类型解析为X。除去不考虑类型变量的限制之外,明显可赋值的关系与正常的赋值关系一致。直观上,当一个类型明显可赋值给另一个类型,我们就能够知道它可以赋值给那些类型的所有实例。 - 否则,这个条件依赖于一个或多个类型变量,有条件的类型解析被推迟进行。
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"
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 分布式条件类型
如果条件类型里待检查的类型是“naked type parameter”,那么它也被称为“分布式条件类型”。分布式条件类型在实例化时会自动分发成联合类型。例如,实例化T extends U ? X : Y,T的类型为A | B | C,会被解析为(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)。
裸类型(naked type parameter):指类型参数没有被包装在其他类型里,比如没有被数组、元组、函数、Promise等等包裹,简而言之裸类型就是未经过任何其他类型修饰或包装的类型。
type T10 = TypeName<string | (() => void)>; // "string" | "function"
type T12 = TypeName<string | string[] | undefined>; // "string" | "object" | "undefined"
type T11 = TypeName<string[] | number[]>; // "object"
1
2
3
2
3
WARNING
与联合类型和交叉类型相似,条件类型不允许递归地引用自己。
extends运用在interface和class中是继承。type中是扩展,虽然也有继承的意思,但是作为条件类型,判断逻辑不同。
interface b {
c: string;
d: number;
}
interface e {
c: string;
}
type a<T> = T extends e ? string : number;
type t = a<b>
//type t = string
let bbb:b = {
c: '123',
d: 123
}
let eee:e = {
c: 'sdd',
}
// 虽然在定义eee时不能写除了c之外的属性 但是赋值的时候是可以的
eee = bbb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20