У меня есть отображение для размеченного объединения от типа объединения к функции, использующей член объединения в качестве параметра:
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 или есть способ настроить типы здесь, сохранив при этом вывод типа и исчерпывающую проверку?