类型保护

我们通常在 JavaScript 中通过判断来处理⼀些逻辑,在 TypeScript 中这种条件语句块还有另外⼀

个特性:根据判断逻辑的结果,缩⼩类型范围(有点类似断⾔),这种特性称为 类型保护 ,触发条

件:

  • 逻辑条件语句块:if、else、elseif

  • 特定的⼀些关键字:typeof、instanceof、in

typeof

1
2
3
4
5
6
7
8
9
10
11
function fn(a: string|number) {
// error,不能保证 a 就是字符串
a.substring(1);
if (typeof a === 'string') {
// ok
a.substring(1);
} else {
// ok
a.toFixed(1);
}
}

instanceof

1
2
3
4
5
6
7
function fn(a: Date|Array<any>) {
if (a instanceof Array) {
a.push(1);
} else {
a.getFullYear();
}
}

in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface IA {
x: string;
y: string; }
interface IB {
a: string;
b: string; }
function fn(arg: IA | IB) {
if ('x' in arg) {
// ok
arg.x;
// error
arg.a;
} else {
// ok
arg.a;
// error
字⾯量类型保护
如果类型为字⾯量类型,那么还可以通过该字⾯量类型的字⾯值进⾏推断
⾃定义类型保护
有的时候,以上的⼀些⽅式并不能满⾜⼀些特殊情况,则可以⾃定义类型保护规则
arg.x;
}
}

字面量类型保护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface IA {
type: 'IA';
x: string;
y: string;
}
interface IB {
type: 'IB';
a: string;
b: string;
}
function fn(arg: IA | IB) {
if (arg.type === 'IA') {
// ok
arg.x;
// error
arg.a;
} else {
// ok
arg.a;
// error
arg.x;
}
}

自定义类型保护

1
2
3
4
5
6
7
8
9
10
11
12
function canEach(data: any): data is Element[]|NodeList {
return data.forEach !== undefined;
}
function fn2(elements: Element[]|NodeList|Element) {
if ( canEach(elements) ) {
elements.forEach((el: Element)=>{
el.classList.add('box');
});
} else {
elements.classList.add('box');
}
}

data is Element[]|NodeList 是⼀种类型谓词,格式为: xx is XX ,返回这种类型的函数就可以

被 TypeScript 识别为类型保护