Типы союзов и утка-ввод текста на машинке

#typescript

Вопрос:

У меня есть функция, которая должна быть в состоянии принять один аргумент, который является либо typeA или typeB . Эти два типа имеют некоторые различные свойства, и мне нужно выполнять операции, используя эти свойства, в зависимости от того, какой это тип.

Я передаю тип объединения функции input : typeA | typeB . Но даже проверка уникальных свойств не помогает. Я получаю ошибку Property 'value' does not exist on type 'typeA | typeB'. Property 'value' does not exist on type 'typeB'.(2339)

код:

 interface typeA {
  name: string;
  value: number;
}
interface typeB {
  name: string;
  data: number;
};

function double(input: typeA | typeB): number {
  if (input.value) {
    return input.value * 2;
  }
  if (input.data) {
    return input.data * 2;
  }
  return 0;
}
 

(Тот же код в машинописной игровой площадке здесь: код)

Есть ли способ справиться с этим?

Комментарии:

1. Вы можете проверить if('value' in input) — это также не приведет к неожиданному поведению, когда значение существует, но равно нулю. Но у вас также есть проблема, потому что подобный объект {name: 'foo': value: 'bar', data: 6} может быть назначен вашему союзу, потому что он может быть назначен typeB . Я предлагаю избегать подобных недискриминационных союзов; иметь свойство помечать каждый объект, с какой ветвью союза он связан, и использовать это свойство для выполнения таких тестов.

2. @kaya3 Спасибо! Я не заметил проблемы с наличием как значения, так и данных. Добавление свойства литерального типа к обоим интерфейсам делает то, что мне нужно.

Ответ №1:

Кажется, это работает:

 if ('value' in input) {
  return input.value * 2;
}
 

Ссылка на игровую площадку