我希望下面的代码能正常工作,但第7行错误并显示消息Type '"one"' is not assignable to type '"two"'.
:
type One = { type: 'one', value: number }
type Two = { type: 'two', value: number }
type OneOrTwo = One | Two
function handleOneOrTwo(oneOrTwo: OneOrTwo): OneOrTwo {
const nextOneOrTwo: OneOrTwo = {
type: oneOrTwo.type,
value: oneOrTwo.value + 1,
}
return nextOneOrTwo
}
这真是令人惊讶。特别是考虑到当我更新该功能以使用switch语句(具有相同功能)时,它可以正常工作:
type One = { type: 'one', value: number }
type Two = { type: 'two', value: number }
type OneOrTwo = One | Two
function handleOneOrTwo(oneOrTwo: OneOrTwo): OneOrTwo {
const nextOneOrTwo = {
value: oneOrTwo.value + 1,
}
switch (oneOrTwo.type) {
case 'one':
return { ...nextOneOrTwo, type: oneOrTwo.type }
case 'two':
return { ...nextOneOrTwo, type: oneOrTwo.type }
default:
throw unreachable(oneOrTwo)
}
}
function unreachable(value: never) {
return new Error(value)
}
即使强制转换类型也不起作用(type: oneOrTwo.type as 'one' | 'two'
)。
我已经阅读了Type Error when trying to extract type from unions的答案,但仍不确定为什么会发生此错误以及如何解决它。
答案 0 :(得分:4)
出现错误的原因是,当您访问联合的type
时是one | two
。但是,当您分配对象文字时,检查的工作方式是,如果对象文字至少与联合的一个成员匹配,则该分配有效。
所以让我们看看。对象文字的类型为{ type : 'one' | 'two' value: number }
。
对象文字类型是否与One
兼容?否,type
在对象文字中为'one' | 'two'
,但在'one'
中为One
对象文字类型是否与Two
兼容?否,type
在对象文字中为'one' | 'two'
,但在'two'
中为Two
因此,您最终得到的对象常量可以分配给联合的任何一个成员。
非类型断言选项是使用扩展表达式,它将保留原始的联合类型:
function handleOneOrTwo(oneOrTwo: OneOrTwo): OneOrTwo {
const nextOneOrTwo: OneOrTwo = {
...oneOrTwo,
value: oneOrTwo.value + 1,
}
return nextOneOrTwo
}
或者使用类型断言:
function handleOneOrTwo(oneOrTwo: OneOrTwo): OneOrTwo {
const nextOneOrTwo: OneOrTwo = {
type: oneOrTwo.type,
value: oneOrTwo.value + 1,
} as OneOrTwo
return nextOneOrTwo
}