简单来说就是类型过滤,能够缩窄类型的范围
typeof
可以通过typeof返回的类型缩小范围,需要注意的是typeofnull
返回的是字符串object,ts在判断时会报错提示
通过Boolean()
可以返回一个type为boolean,value为true的类型
通过!!world
可以返回一个type为true,value为true的类型(一个狭窄的文字布尔类型 true)
平等缩小
指的是通过===
、!==
、==
、!=
判断类型是否相同,,可以配合联合类型使用
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function example(x: string | number, y: string | boolean) { if (x === y) { x.toUpperCase(); (method) String.toUpperCase(): string y.toLowerCase(); (method) String.toLowerCase(): string } else { console.log(x); (parameter) x: string | number console.log(y); (parameter) y: string | boolean } }
|
通过in收窄
通常搭配联合类型使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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;
} else { animal;
} }
|
instanceof
通过判断实例是否再原型上来收窄类型范围
1 2 3 4 5 6 7 8 9 10 11
| function logValue(x: Date | string) { if (x instanceof Date) { console.log(x.toUTCString());
} else { console.log(x.toUpperCase());
} }
|
Assignments
ts能根据右侧的赋值适当的收窄左侧
1 2 3 4 5 6 7 8
| let x = Math.random() < 0.5 ? 10 : "hello world!";
x = 1; console.log(x);
|
这些分配中的每一个都是有效的,这是因为一开始x被赋值了number或string类型
控制语句
基于可达性的代码分析称为控制流分析。TypeScript 在遇到类型保护和赋值时使用这种流分析来缩小类型。当分析一个变量时,控制流可以一次又一次地分裂和重新合并,并且可以观察到该变量在每个点具有不同的类型
使用类型谓词
定义一个返回类型为类型谓词的函数
谓词采用 形式 parameterName is Type 其中parameterName必须是当前函数签名中的参数名称
感觉上像是自定义了一个用于收窄类型的函数返回值类型
举例说明
1 2 3 4 5 6 7 8 9 10 11 12
| function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; }
let pet = getSmallPet(); if (isFish(pet)) { pet.swim(); } else { pet.fly(); }
|
Discriminated unions
为了让ts能够更准确的检查,当我们通过一些属性去判断参数的类型时,编译器往往无法正确判断属性是否存在。虽然我们可以通过类型断言和非空声明解决,但应该有更好的办法。
我们需要将我们所知道的信息传达给类型检查器,可以更详细的声明类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| interface Circle { kind: "circle"; radius: number; } interface Square { kind: "square"; sideLength: number; } type Shape = Circle | Square;
function getArea(shape: Shape) { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2;
case "square": return shape.sideLength ** 2;
} }
|
never 类型
缩小范围时,可以将联合的选项减少到已消除所有可能性并且一无所有的程度。在这些情况下,TypeScript 将使用一种never类型来表示不应该存在的状态。
穷举检查
never类型可以分配给任何类型,但是没有类型能够分配给never(never本身除外)。所以我们可以通过在switch语句中的default下通过赋值never来检查条件是否都考虑充分,ts会帮我们自动进行穷举检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| interface Triangle { kind: "triangle"; sideLength: number; } type Shape = Circle | Square | Triangle; function getArea(shape: Shape) { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.sideLength ** 2; default: const _exhaustiveCheck: never = shape;
return _exhaustiveCheck; } }
|