TypeScript条件自定义类型解构提示属性不存在如何解决
报错原因
FooOrBar属于联合类型,TypeScript对联合类型的属性访问有明确约束:仅当某个属性存在于联合类型的所有分支中时,才允许直接访问该属性。你的联合类型两个分支分别只包含foo、bar属性,不存在共有属性,因此直接解构两个属性会触发类型报错。
可行重构方案
方案1:用in操作符做类型收窄(最推荐,完全保留原逻辑)
in是TypeScript原生支持的类型收窄语法,可通过判断属性是否存在于对象上,自动把联合类型收窄到对应分支,不需要提前解构:
type FooOrBar = { foo: string } | { bar: string } function doSomething(obj: FooOrBar) { if ('foo' in obj) { // 此分支内TS自动推导obj类型为{ foo: string },可安全访问obj.foo // 执行foo相关处理逻辑 return } if ('bar' in obj) { // 此分支内TS自动推导obj类型为{ bar: string },可安全访问obj.bar // 执行bar相关处理逻辑 return } throw new Error('入参必须包含foo或bar属性') }
方案2:改造类型定义兼容解构写法
如果需要保留函数入口统一解构的写法,可以给联合类型的互斥属性补充可选的never类型标记,既允许同时访问两个属性,又能保留属性互斥的约束:
type FooOrBar = { foo: string; bar?: never } | { bar: string; foo?: never } function doSomething(obj: FooOrBar) { const { foo, bar } = obj // 此处解构不会触发类型报错 if (foo) { // 此分支内TS自动推导bar为undefined,不会出现同时传两个属性的情况 // 执行foo相关处理逻辑 return } if (bar) { // 此分支内TS自动推导foo为undefined // 执行bar相关处理逻辑 return } throw new Error('入参必须包含foo或bar属性') }
补充的
bar?: never、foo?: never标记会让TS校验时禁止传入同时包含foo和bar属性的对象,完全符合你最初的互斥类型设计。
避坑提示
不要使用as any、// @ts-ignore这类方式强制跳过类型校验,这类写法会丢失TypeScript的类型保护能力,后续代码迭代时极易引入隐藏bug。
内容的提问来源于stack exchange,提问作者KGE
相关产品推荐
相关产品推荐

