TypeScript 利用 `never` 配合 `switch`穷举目标类型
source link: https://wayou.github.io/2021/09/10/TypeScript_%E5%88%A9%E7%94%A8__never__%E9%85%8D%E5%90%88__switch_%E7%A9%B7%E4%B8%BE%E7%9B%AE%E6%A0%87%E7%B1%BB%E5%9E%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
TypeScript 利用 `never` 配合 `switch`穷举目标类型
2021 9 月 10 日
TypeScript 利用 never
配合 switch
穷举目标类型
never
类型可赋值给任意类型,反之不然,除非是 never
本身。复用该特性可对类型进行收窄(narrowing)操作。常见的使用场景是和 switch
语句搭配,达到保证 switch 穷举了目标所有可能值的目的。这个被 switch 的目标可以是 union 联合类型,也可以是 enum 枚举类型等。
考察如下示例代码,其中 Shape
类型包含一个形状种类的字段,该字段为一个枚举可包含多个可能的值:
enum ShapeKind {
Circle,
Square,
}
interface Shape {
kind: ShapeKind;
radius?: number;
sideLength?: number;
}
那么在计算对象面积时,需要根据不同类型来决定如何计算:
function getArea(shape: Shape) {
switch (shape.kind) {
case ShapeKind.Circle:
return Math.PI * shape.radius ** 2;
case ShapeKind.Square:
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape.kind; // (property) Shape.kind: never
return _exhaustiveCheck;
}
}
通过前面 switch
语句,每条 case
都会将类型收窄,最后到 default
时 kind
就是 never
类型了。我们将它赋值给一个 never
类型的变量 _exhaustiveCheck
备用。
此时如果前面 case
少写了,或者后续有人将枚举进行扩充,添加了新的类型,
enum ShapeKind {
Circle,
Square,
+ Triangle,
}
此时 default
处 kind
就不是 never
类型了。由于文章开头提到的原因,任意类型(除了 never
自身)无法赋值给 never
类型,所以此处会报错:
const _exhaustiveCheck: never = shape.kind; // ❌ Type 'ShapeKind' is not assignable to type 'never'.ts(2322)
从而达到了保护作用,提示我们把新增的类型在 switch
语句中补上。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK