将类型推导为更精确类型的过程
收窄方法
typeof
使用 typeof 判断变量类型进行收窄
function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") { // 收窄成 number
return " ".repeat(padding) + input
}
return padding + input
}
真值收窄(Truthiness narrowing)
if
条件语句会自动将结果转换为 boolean 类型,也可以使用 Boolean()
函数强制转为 boolean 值,或者使用更加简短的 !!
function printAll(strs: string | string[] | null) {
if (strs && typeof strs === "object") { // 收窄成 string[]
for (const s of strs) {
console.log(s)
}
} else if (typeof strs === "string") { // 收窄成 string
console.log(strs)
}
}
等值收窄(Truthiness narrowing)
使用 switch
语句和等值检查比如 ===
!==
==
!=
去收窄类型
function printAll(strs: string | string[] | null) {
if (strs !== null) { // 收窄成 string | string[]
if (typeof strs === "object") { // 收窄成 string[]
for (const s of strs) {
console.log(s)
}
} else if (typeof strs === "string") { // 收窄成 string
console.log(strs)
}
}
}
in
判断一个对象是否有对应的属性名
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) { // 收窄成 Fish
return animal.swim()
}
return animal.fly()
}
instanceof
function logValue(x: Date | string) {
if (x instanceof Date) { // 收窄成 Date
console.log(x.toUTCString())
} else {
console.log(x.toUpperCase())
}
}
可辨别联合(Discriminated unions)
当联合类型中的每个类型,都包含了一个共同的字面量类型的属性(也叫可辩别属性),那么就可以根据这个可辩别属性的值来区分出不同的类型
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": // 收窄为 Circle
return Math.PI * shape.radius ** 2
case "square": // 收窄为 Square
return shape.sideLength ** 2
}
}