条件类型的语法实际上就是三元表达式,举例 T extends U ? X : Y
条件类型 Conditional Types
通常我们看到的条件类型是和泛型一起使用的,使用条件类型可以根据使用者的传入参数类型来判别确定的类型。
function pickSingleValue<T extends object, U extends keyof T>(
obj: T,
key: U
): T[U] {
return obj[key]
}
T extends object
与U extends keyof T
都是泛型约束,分别将T约束为对象类型和将U约束为T键名的字面量联合类型,我们通常使用泛型约束来做收窄类型约束。
以一个条件类型作为函数返回值的例子
declare function strOrNum<T extends boolean>(x: T): T extends true ? string : number
const strReturnType = strOrNum(true); //string
const numReturnType = strOrNum(false); //number
在上面那种情况下,条件类型的判断会被延迟,因为此时的类型系统没有足够的信息来完成判断,只有待使用者调用该函数(入参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
分发条件类型 Distributive Conditional Types
在泛型中使用条件类型的时候,如果传入的是一个联合类型,就会变成分发的(distributive)
type ToArray<T> = T extends any ? T[] : never
type StrArrOrNumber = ToArray<string | number>
我们在使用的时候传入一个联合类型,这个条件类型就会被应用到联合类型的每个成员
这个过程,当我们在StrArrOrNumber传入string | number
,接下来遍历联合类型里的成员,相当于
ToArray<string> | ToArray<number>
,所以结果为string[] | number[]