根据流程控制的一些分支上的判断,可以将申明时的类型指向更具体的类型,这个过程叫类型收窄。
typeof 类型守卫
function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") {
// (parameter) padding: number
return " ".repeat(padding) + input;
}
// (parameter) padding: string
return padding + input;
}
typeof操作符可以判断出的具体类型
"string""number""bigint""boolean""symbol""undefined""object""function"
真值判断收窄
function printAll(strs: string | string[] | null) {
// typeof null : Object
if (strs && typeof strs === "object") {
// strs: string[]
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
等于判断收窄
function example(x: string | number, y: string | boolean) {
if (x === y) {
// We can now call any 'string' method on 'x' or '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操作符收窄
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
return animal.swim();
}
return animal.fly();
}
instanceof操作符收窄
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
// (parameter) x: Date
} else {
console.log(x.toUpperCase());
// (parameter) x: string
}
}
赋值
let x = Math.random() < 0.5 ? 10 : "hello world!";
// x: string | number
x = 1;
// x: number
x = "goodbye!";
// x: string
控制流分析
function example() {
let x: string | number | boolean;
// x: boolean
x = Math.random() < 0.5;
if (Math.random() < 0.5) {
// x: string
x = "hello";
} else {
// x: number
x = 100;
}
// x: string | number
return x;
}
断言
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
Discriminated unions
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
type Shape = Circle | Square;
function getArea(shape: Shape) {
if (shape.kind === "circle") {
// shape: Circle
return Math.PI * shape.radius ** 2;
}
}
never类型
ts会使用never类型来呈现不可能存在的状态。
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;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}