Почему эти структурно похожие типы несовместимы? - PullRequest
3 голосов
/ 09 мая 2020

Если я объявляю следующие типы:

export type Type1 = { id: string } | { id: number };
export type Type2 = { id: string } | { id: number };

Почему я получаю ошибку при использовании следующим образом:

function displayItem(item: Type1) {
  loadItem({ id: item.id });          // error is indicated here
}

function loadItem(item: Type2) {}

enter image description here

Насколько я понимаю из https://www.typescriptlang.org/docs/handbook/type-compatibility.html, они должны быть эквивалентными, поскольку они одинаковы по структуре.

Более простое воспроизведение в свете ответов (второй тип - не требуется):

export type Type1 = { id: string } | { id: number };

function displayItem(item: Type1) {
   loadItem({ id: item.id });          // error is indicated here
}

function loadItem(item: Type1) {}

Ответы [ 2 ]

3 голосов
/ 09 мая 2020

По сути, вы пытаетесь присвоить значение типа number | string либо number, либо string.

Поскольку вы получаете доступ к item.id, id может быть string или number, по определению вашего типа. Ваш Type2 ожидает объект {id: string} или {id: number}, который отличается от {id: string | number}.

Итак, два разных сценария ios могут решить эту проблему.

  1. Объявите свой Type2, чтобы ожидать один ключ с именем id, который равен number | string
  2. Передайте весь объект item вашей второй функции. Это так называемая совместимость типа
3 голосов
/ 09 мая 2020

Дело не в том, что Type1 не эквивалентно Type2

Например, следующее не приведет к ошибке

function displayItem(item: Type1) {
  loadItem(item);
}

function loadItem(item: Type2) {}

Проблема возникает, когда вы набираете item.id что могло быть две вещи. Поскольку Type1 определяется как export type Type1 = { id: string } | { id: number };, тип этой переменной может быть string или number. Таким образом, машинописный текст создает другой тип для {id: item.id}, который равен {id: number | string}, как вы видите, он несовместим с Type2.

Вы должны явно указать, какой тип вы хотите использовать.

Следующее сообщение не даст никаких ошибок

function displayItem(item: Type1) {
  loadItem({ id: item.id as number});         
}

Теперь я помечу item.id как number, поэтому тип { id: item.id as number} равен {id: number}, который совместим с Type2

Просто измените свои типы на следующие

export type Type1 = { id: string | number};
export type Type2 = { id: string | number};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...