联合类型中离散成员的属性类型兼容性问题
联合类型中离散成员的属性类型兼容性问题
我之前还以为自己搞定过这个问题呢,结果现在又栽在这上面了。咱们先来看这个联合类型的定义:
type Handler<T> = (value: T) => void; type Foo = { a: string; b: Handler<string> } | { a : number; b: Handler<number> }
现在假设有一个符合Foo类型的对象x,我本来想着直接这么写代码就行:
x.b(x.a);
但实际操作起来却会遇到类型报错——这是因为TypeScript没办法自动推断出x.a和x.b的类型是严格匹配的。毕竟x是联合类型,它可能是{a: string; b: Handler<string>},也可能是{a: number; b: Handler<number>},TS没办法确定这两个属性属于联合类型的同一个分支,所以会认为x.a可能是string或number,而x.b可能接受string或number,两者的类型组合不兼容。
要解决这个问题,我们可以用类型收窄的方式,让TS明确知道x属于联合类型的哪一个分支。比如直接用typeof做类型收窄:
if (typeof x.a === 'string') { x.b(x.a); // 这里TS能确定x.a是string,x.b接受string,完全没问题 } else { x.b(x.a); // 剩下的分支必然是number类型,同样能正常运行 }
如果场景更复杂,也可以自定义类型守卫函数来做收窄:
function isStringFoo(foo: Foo): foo is { a: string; b: Handler<string> } { return typeof foo.a === 'string'; } function isNumberFoo(foo: Foo): foo is { a: number; b: Handler<number> } { return typeof foo.a === 'number'; } // 使用时 if (isStringFoo(x)) { x.b(x.a); } else if (isNumberFoo(x)) { x.b(x.a); }
这样就能让TS正确识别属性之间的类型对应关系,顺利执行x.b(x.a)的操作啦。
备注:内容来源于stack exchange,提问作者flq
相关产品推荐
相关产品推荐

