type guard
对于联合类型,需要进行类型收窄。此时需要 if 或者 typeof 对类型进行收窄,进行类型守卫。
typeof
typeof 操作符可以得到值的基础类型,如,string,number,bigint,boolean,symbol,undefined,object,function。但是,没有 null。
TS会再次校验typeofd返回值,这也是一种 type guard。
如下,虽然使用 typeof 收窄了类型,但是 JavaScritp 中 null 是一个object,TypeScript也会提示报错。
// @errors: 2531
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
for (const s of strs) {
//Object is possibly 'null'.Object is possibly 'null'.
console.log(s);
}
}
else if (typeof strs === "string") {
console.log(strs);
} else {
// do nothing
}}
TS 只是把 strs 类型收窄成了 string[] | null。
Truthiness narrowing
TypeScript 只会帮助我们进行类型检查,如果在类型收窄时不留意变量的值,那么在JS运行中,就可能会隐藏bug了。
function printAll(strs: string | string[] | null) {
// !!!!!!!!!!!!!!!!
// DON'T DO THIS!
// KEEP READING
// !!!!!!!!!!!!!!!!
if (strs) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
}
else if (typeof strs === "string") {
console.log(strs);
}
}
}
in 操作符
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void, fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
// animal (parameter) animal: Fish | Human
} else {
// animal (parameter) animal: Bird | Human
}
}
instanceof 操作符
也会进行类型收窄
赋值
略
Control flow analysis
This analysis of code based on reachability is called control flow analysis。TS 会基于此,即,TS会对在不同分支逻辑中的变量进行分析,从而类型收窄。
类型预测
parameterName is Type, 同时 parameterName必须是函数签名中形参的名称。
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
TODO
对于 class,可以使用 this is Type 进行类型收窄
www.typescriptlang.org/docs/handbo…
可辨识联合 -> Discriminated unions
```TypeScript```
interface Shape { kind: "circle" | "square"; radius?: number;
sideLength?: number;}// 虽然利用 === 对 kind 进行了类型收窄,但是得用 ! 来"证实" shape.radius 一定存在
function getArea(shape: Shape) { if (shape.kind === "circle") { return Math.PI * shape.radius! ** 2; }}
// 优化一下 利用字面量类型与联合类型进行收窄
interface Circle { kind: "circle"; radius: number;}
interface Square { kind: "square"; sideLength: number;}type Shape = Circle | Square;
// 优化function getArea(shape: Shape) { if (shape.kind === "circle") { return Math.PI * shape.radius ** 2; }}
never 类型
在类型收窄时,可以降低联合类型的选项。当收窄到一点的时候,已经除去了所有的可能性,应该没有任何类型剩余。在TS中,never表示一种不应该存在的状态。
never类型可以赋值给任何类型,但是只有never类型可以赋值给never类型。
Exhaustiveness checking
通过never类型,确保代码联合类型变动之后,所有的类型都被穷尽了。预防bug。