Вызов функции из карты типов объединения

У меня есть отображение для размеченного объединения от типа объединения к функции, использующей член объединения в качестве параметра:

export interface Truncate {
  type: 'truncate'
  maxLength: number
}

export interface Append {
  type: 'append'
  suffix: string
}

export type Applicable = Truncate | Append

const applicableMap: { [K in Applicable['type']]: (base: string, applicable: Extract<Applicable, { type: K }>) => string } = {
  'truncate': (s, applicable) => {
    return s.slice(0, applicable.maxLength)
  },
  'append': (s, applicable) => {
    return s + applicable.suffix
  }
}

Все идет нормально; TypeScript правильно определяет типы аргумента applicable в каждой функции и выполняет исчерпывающую проверку ключей, поэтому я не забываю случайно добавить запись на карту, если добавляю новый член.

Теперь у меня есть apply функция, которая выбирает функцию на карте и пытается ее вызвать:

function apply(s: string, applicable: Applicable): string {
  return applicableMap[applicable.type](s, applicable)
}

Однако не удается скомпилировать из-за следующего:

Аргумент типа «Применимо» не может быть назначен параметру типа «никогда».
Пересечение «Добавить и добавить» было сокращено до «никогда», потому что свойство «тип» имеет конфликтующие типы в некоторых составляющих.
Тип » Добавить 'нельзя присвоить типу' never '. Ts (2345)

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

Единственное исправление, которое я нашел до сих пор, - это назвать его как applicableMap[applicable.type](s, applicable as any), однако я считаю, что использование any всегда является хакерским.


Теперь вопрос:

Это просто текущее ограничение TypeScript или есть способ настроить типы здесь, сохранив при этом вывод типа и исчерпывающую проверку?


person Peter Uhnak    schedule 04.04.2021    source источник


Ответы (1)


Проверьте https://github.com/microsoft/TypeScript/issues/30581, который кажется признанным ограничением в компиляторе Typescript и, как мне кажется, имеет примерно такую ​​же форму, как и ваша проблема.

person cefn    schedule 04.04.2021
comment
Спасибо за ссылку! Это действительно похоже на ту же проблему. - person Peter Uhnak; 04.04.2021