简体   繁体   English

在TypeScript中将变量定义为已区分联合的一种变体

[英]Defining a variable as one variant of a discriminated union in TypeScript

I have the following typescript code which uses a discriminated union to distinguish between some similar objects: 我有以下打字稿代码,该代码使用区分的联合来区分某些相似的对象:

interface Fish  {
  type: 'FISH',
}

interface Bird  {
  type: 'BIRD',
  flyingSpeed: number,
}

interface Ant  {
  type: 'ANT',
}

type Beast = Fish | Bird | Ant

function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
    const myBeast: Beast = animal === 'BIRD' ? {
        type: animal,
        flyingSpeed: 10
    } : {type: animal}
}

In the function buildBeast it accepts a string that complies with all possible types of my Beast type, yet it does not allow me to declare the myBeast as type Beast due to this error: 在函数buildBeast它接受一个符合我的Beast类型所有可能types的字符串,但是由于此错误,它不允许我将myBeast声明为Beast类型:

Type '{ type: "BIRD"; flyingSpeed: number; } | { type: "FISH" | "ANT"; }' is not assignable to type 'Beast'.
  Type '{ type: "FISH" | "ANT"; }' is not assignable to type 'Beast'.
    Type '{ type: "FISH" | "ANT"; }' is not assignable to type 'Ant'.
      Types of property 'type' are incompatible.
        Type '"FISH" | "ANT"' is not assignable to type '"ANT"'.
          Type '"FISH"' is not assignable to type '"ANT"'.

It seems that all cases still yield a correct Beast yet TS seems to have trouble coercing the different types. 似乎所有情况下都能产生正确的Beast但TS似乎难以强制使用不同的类型。 Any ideas? 有任何想法吗?

TypeScript doesn't do control flow analysis by walking through union types and making sure that each type works. TypeScript不会通过遍历联合类型并确保每种类型都起作用来进行控制流分析 It would be nice if it did so or if you could tell it to do so, and in fact I've made a suggestion to that effect, but it isn't currently possible. 如果这样做,或者您可以告诉它这样做,那将是很好的,实际上我已经对此提出了建议 ,但目前尚不可能。

For now, the only way to deal with it that I know of are the workarounds I mention in that suggestion: either do a type assertion (which is unsafe) or walk the compiler through the different cases (which is redundant). 就目前而言,我知道的唯一解决方法是我在该建议中提到的解决方法:执行类型声明(这是不安全的)或在编译器中处理不同的情况(这是多余的)。 Here are the two different ways: 这是两种不同的方式:

Assertion: 断言:

function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
  const myBeast: Beast = animal === 'BIRD' ? {
    type: animal,
    flyingSpeed: 10
  } : {type: animal} as Fish | Ant;
}

Walk compiler through different cases: 逐步介绍编译器的不同情况:

function buildBeast(animal: 'FISH' | 'BIRD' | 'ANT') {
  const myBeast: Beast = animal === 'BIRD' ? {
    type: animal,
    flyingSpeed: 10
  } : (animal === 'FISH') ? { 
    type: animal 
  } : { type: animal };
}

Hey, if you think that TypeScript should allow you to distribute control flow analysis over union types, maybe head over to that suggestion and give it a 👍 or describe your use case. 嘿,如果您认为TypeScript应该允许您将控制流分析分布在联合类型上,则可以直接参考该建议并给它一个a或描述您的用例。 Or, if those above solutions work for you, that's great too. 或者,如果上述解决方案对您有用,那也很好。

Hope that helps. 希望能有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM