使用Omit处理函数参数时TypeScript丢失类型信息问题
解决TypeScript中联合类型使用Omit后的类型收窄错误
问题原因
你遇到的错误是因为Omit<Foo, 'value'>的行为和预期不符。当Omit作用于联合类型时,它会对每个联合成员单独执行Omit操作:
- 原Foo中的
{ value: string }去掉value属性后变成空对象{} - 另外两个成员
{ oldValue: string }和{ newValue: string }不受影响(因为它们没有value属性)
最终Omit<Foo, 'value'>的实际类型是{} | { oldValue: string } | { newValue: string },这就导致:
- 检查
'oldValue' in input时,input可能是空对象{},所以input.oldValue被推断为unknown,无法赋值给string - 最后返回
input.newValue时,input可能是空对象或{ oldValue: string },这两种类型都没有newValue属性,所以报错
解决方案
不要用Omit,直接从Foo中排除带有value属性的成员,或者显式定义目标类型:
方案1:使用Exclude排除指定成员
type Foo = { value: string } | { oldValue: string } | { newValue: string }; function getResults(input: Foo): string { if ('value' in input) { return input.value; } if ('oldValue' in input) { return input.oldValue; } return input.newValue; } function getResults2(input: Exclude<Foo, { value: string }>): string { if ('oldValue' in input) { return input.oldValue; } return input.newValue; }
Exclude<Foo, { value: string }>会直接从联合类型Foo中移除匹配{ value: string }的成员,得到的类型是{ oldValue: string } | { newValue: string },此时类型收窄可以正常工作,不会出现错误。
方案2:显式定义目标类型
如果逻辑简单,也可以直接写出需要的类型,更直观:
type Foo = { value: string } | { oldValue: string } | { newValue: string }; type FooWithoutValue = { oldValue: string } | { newValue: string }; function getResults(input: Foo): string { if ('value' in input) { return input.value; } if ('oldValue' in input) { return input.oldValue; } return input.newValue; } function getResults2(input: FooWithoutValue): string { if ('oldValue' in input) { return input.oldValue; } return input.newValue; }
内容的提问来源于stack exchange,提问作者Evanss
相关产品推荐
相关产品推荐

