如图,声明的filter
是个联合类型,一部分有days
属性一部分没有(下面的判断同理)
一个个判断是否含有该属性实在是太不优雅了
然而注释掉的这种写法也会报ts错误,同样的不能这样写
是否有更优雅的写法呢?
这里有个demo能帮忙阐述我的问题
interface A{
a: string
}
interface B{
b: number
}
interface C{
c: string
}
type ABC = A | B | C
const fn = (param: ABC) => {
const obj = param.b // 这里无法通过ts检查,因为属性b并不是一定存在的
// 在官方实例中,这种情况应该使用类型保护,也就是下方的写法
// 但实际业务中通常需要访问很多属性,要一个个in判断实在是太冗余了
// 有更优雅的写法吗?
// if ('b' in param) {
// obj = param.b
// }
return obj
}
###param
所拥有的属性并不能非常明确的确定,TypeScript 就不能安全的判断哪些属性可用,哪些不可用,所以不会通过检查。
如果要让 TypeScript 明白,属性确实可用,那就必须证明 param
确实是某种类型,这不是抽象层面的,而是实现层面的。通常在 JS 中我们会这么检查:
if (param.b) {
// 这说明 param 中有 b 这个属性,符合 B 类型的特征
}
在 TypeScript 中可以定义一个 isB()
函数来进行判断,
function isB(it: ABC): it is B {
return (it as B).b !== undefined;
}
注意它的返回类型,不是单纯的 boolean
,而是一个类型判定,有了这个判定函数之后,就可以在业务代码中这样写:
const fn = (param: ABC) => {
if (isB(param)) {
const obj = param.b; // 这里就可以识别 param 是 B 类型了
}
}