类型保护 - 10
类型保护
- 类型保护就是一些表达式,他们在编译的时候就能通过类型信息确保某个作用域内变量的类型
- 类型保护就是能够通过关键字判断出分支中的类型
1 typeof 类型保护
function double(input: string | number | boolean) {
if (typeof input === "string") {
input.toLocaleLowerCase()
} else if (typeof input === "number") {
input.toFixed()
} else {
input
}
}
2 instanceof 类型保护
class Animal {
public name: string = "ruhua"
}
class Bird extends Animal {
public swing: number = 2;
}
function getName(a: Animal) {
if (a instanceof Bird) {
a.swing;
a.name;
} else {
// a.swing; // 报错
a.name;
}
}
3 null 类型保护
function getFirstLetter(s: string | null) {
if (s === null) {
s = ""
}
return s.charAt(0)
}
4 链判断运算符
- 链判断运算符是一种先检查属性是否存在,在尝试访问该属性的运算符,其符号为 ?.
- 如果运算符左侧的操作数 ?. 计算为 undefined 或 null,则表达式求值为 undefined。否则,正常触发目标属性访问,发放或函数调用
a?.b;
a == null ? undefind : a.b;
a?.[x];
a == null ? undefind : a[x];
a?.b();
a == null ? undefind : a.b();
a?.();
a == null ? undefind : a();
链判断运算符还处于 stage1 阶段(征求意见阶段),TS 也暂时不支持
5 可辨识的联合类型
- 就是利用联合类型中的共有字段进行类型保护的一种技巧
- 相同字段的不同取值就是可辨识
interface WarningButton {
class: "warning", // 字面量类型
text1: "修改"
}
interface DangerButton {
class: "danger",
text2: "删除"
}
type Button = WarningButton | DangerButton;
function getButton(button: Button) {
if (button.class === "warning") {
button.text1
} else {
button.text2
}
}
6 in 操作符
interface Bird {
swing: number
}
interface Dog {
leg: number
}
function getNumber(x: Bird | Dog) {
if ("swing" in x) {
x.swing
} else {
x.leg
}
}
7 自定义的类型保护
- TS 里的类型保护本质上就是一些表达式,他们会在运行时检查类型信息,以确保在某个作用域里的类型是符合预期的
- 要自定义一个类型保护,只需要简单地为这个类型保护定义一个函数即可,这个函数的返回值是一个类型谓词
- 类型谓词的语法为
parameterName is Type这种形式,其中parameterName必须是当前函数签名里的一个参数名
interface Bird {
name1: "bird"
legs: number
}
interface Dog {
name2: "dog"
legs: number
}
function isBird(x: Bird | Dog): x is Bird {
return x.legs === 2;
}
function getAnimal(x: Bird | Dog) {
if (isBird(x)) {
console.log(x.name1); // x 是 Bird 类型
} else {
console.log(x.name2); // x 是 Dog 类型
}
}
let x: Bird = { name1: "bird", legs: 2 }
getAnimal(x)

浙公网安备 33010602011771号