尝试更新标签联合时,令人惊讶的错误类型

问题描述 投票:3回答:1

我希望下面的代码工作得很好,但第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但我仍然不能确定为什么这错误发生和如何解决它。

typescript
1个回答
4
投票

你得到一个错误的原因是因为当你进入联盟的typeone | 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
} 
© www.soinside.com 2019 - 2024. All rights reserved.