Определение переменной как одного из вариантов различаемого объединения в TypeScript - PullRequest
0 голосов
/ 27 июня 2018

У меня есть следующий машинописный код, который использует различающееся объединение, чтобы различать некоторые похожие объекты:

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}
}

В функции buildBeast она принимает строку, которая соответствует всем возможным types моего типа Beast, но не позволяет мне объявить 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"'.

Похоже, что все случаи все еще дают правильный Beast, но TS, похоже, испытывает проблемы с приведением различных типов. Есть идеи?

1 Ответ

0 голосов
/ 27 июня 2018

TypeScript не выполняет управления потоком анализа , просматривая типы объединения и следя за тем, чтобы каждый тип работал. Было бы неплохо, если бы это было так или вы могли бы сказать это сделать, и на самом деле я сделал предложение на этот счет, но в настоящее время это невозможно.

На данный момент единственный способ справиться с этим, о котором я знаю, - это обходные пути, о которых я упомянул в этом предложении: либо сделайте утверждение типа (что небезопасно), либо проведите компилятор через различные случаи (который является избыточным). Вот два разных способа:

Утверждение:

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

Пройдите компилятор по разным случаям:

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

Эй, если вы думаете, что TypeScript должен позволить вам распределить анализ потока управления по типам объединения, возможно, перейдите к этому предложению и дайте ему ? или опишите ваш вариант использования. Или, если указанные выше решения работают для вас, это тоже замечательно.

Надеюсь, это поможет. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...