前段时间在专心工(摸)作(🐟)的时候,在交流群看到了一个群友的求助:如何让下图中这段代码不报错
使用 as 并不能解决问题,as 只对编译期类型校验有效且只是临时收窄变量的类型。而且这里出现了 if 条件判断,这样并不会收窄 data 的类型,在分支里面,data 的类型 还是 Tdata
使用 as 的场景应该是你十分确定数据的类型时才可以使用。
比如下面这段代码,但这种代码十分的不优雅。
if(hasCode(data)) {
console.log((data as Ia).code);
}
我给出的答案是
interface IA {
name: string;
code: number;
}
interface IB {
name: string;
age: string;
}
type IC = IA | IB;
function test(data: IC) {
if ("code" in data) {
console.log(data.code); // data: IA
} else {
console.log(data.age); // data: IB
}
}
但是有同学指出,使用in运算符会往原型链上面找
OK fine,我只能祭出了终极武器:自定义类型守卫(User-Defined Type Guards)
function isIA(data: any): data is IA {
return typeof data.code !== "undefined";
}
function test(data: IC) {
if (isIA(data)) {
console.log(data.code); // data: IA
} else {
console.log(data.age); // data: IB
}
}
内置 Type Guard
typescript 类型判断有以下三种,分别适用于不同场景
- typeof,适用于判断基本类型
- instanceof,适用于判断类
- in,适用于判断对象
这几个都是属于 js 的运算符,运行时也会起作用,不单单是编译期进行类型判断
自定义 Type Guard
很多人可能也写过这种代码:
if(typeof val === 'string') {
val.split(''); // ok
}
function isStr(val: any) {
return typeof val === 'string';
}
if(isStr(val)) {
val.split(''); // Property 'split' does not exist
}
有没有觉得很奇怪,只是把一段代码封装成函数,typescript 就不认识了(没得办法,typescript还没那么智能到可以知道你函数里做了什么)
function isIA(data: any): data is IA {
return typeof data.code !== "undefined";
}
解决办法就是使用上面那段代码,使用自定义Type Guard
使用方法如下段代码:在声明函数返回值类型的地方写 val is Type,Type 是你要判断的类型
function myTypeGuard(val: any): val is Type;