# 高级类型之条件类型
之所以叫类型编程,是因为我们可以对类型进行编程了,比如之前我们的类型基本都是写死的,比如这样:
type F = string
@前端进阶之旅: 代码已经复制到剪贴板
但是有时候我们并不能再编写代码的时候就把类型确定了,到底是什么类型还是需要一些外部条件的,那么这个时候应该怎么办?
TypeScript 在2.8版本之后引入了条件类型(conditional type).
# 条件类型的使用
条件类型够表示非统一的类型,以一个条件表达式进行类型关系检测,从而在两种类型中选择其一:
T extends U ? X : Y
@前端进阶之旅: 代码已经复制到剪贴板
上面的代码可以理解为: 若 T 能够赋值给 U,那么类型是 X,否则为 Y,有点类似于JavaScript中的三元条件运算符.
比如我们声明一个函数 f,它的参数接收一个布尔类型,当布尔类型为 true 时返回 string 类型,否则返回 number 类型:
declare function f<T extends boolean>(x: T): T extends true ? string : number;
const x = f(Math.random() < 0.5)
const y = f(false)
const z = f(true)
@前端进阶之旅: 代码已经复制到剪贴板
而 x,y,z 的类型分别如下:



条件类型就是这样,只有类型系统中给出充足的条件之后,它才会根据条件推断出类型结果.
# 条件类型与联合类型
条件类型有一个特性,就是「分布式有条件类型」,但是分布式有条件类型是有前提的,条件类型里待检查的类型必须是naked type parameter.
好了,肯定有人已经晕了,什么是分布式有条件类型?naked type parameter又是什么?
naked type parameter指的是裸类型参数,怎么理解?这个「裸」是指类型参数没有被包装在其他类型里,比如没有被数组、元组、函数、Promise等等包裹.
我们举个简单的例子:
// 裸类型参数,没有被任何其他类型包裹即T
type NakedUsage<T> = T extends boolean ? "YES" : "NO"
// 类型参数被包裹的在元组内即[T]
type WrappedUsage<T> = [T] extends [boolean] ? "YES" : "NO";
@前端进阶之旅: 代码已经复制到剪贴板
好了,naked type parameter我们了解了之后,「分布式有条件类型」就相对容易理解了,按照官方文档的说法是「分布式有条件类型在实例化时会自动分发成联合类型」.
这个说法很绕,我们直接看例子:
