Я бы хотел определить функцию, которая может принимать параметры, набранные одним из двух способов. Например:
type Fn = {
(abc: number, def: string): void,
(abc: string): void,
};
С учетом сигнатуры этого типа, если abc
является числом, то def
является строкой, а если abc
является строкой, то def
не определено. Это понятно людям, но может ли Typescript это распознать? Например, следующая реализация завершается ошибкой:
const fn: Fn = (abc: number | string, def?: string) => {
if (typeof abc === 'string') console.log(abc.includes('substr'));
else console.log(def.includes('substr'));
}
, поскольку, хотя тип abc
был сужен, TS не понимает, что тип def
также был определен, поэтому def.includes
не допускается Группировка типов аргументов распознается для вызывающих абонентов функции, поэтому следующее, как и ожидалось, запрещено:
fn('abc', 'def');
Но перегруженная группировка типов, похоже, не действует внутри функции .
Когда есть только пара параметров, достаточно просто явно (и с избыточностью) проверить тип каждого параметра или использовать утверждение типа для каждого после проверки, но это по-прежнему ужасно. Когда параметров больше, чем пара параметров, становится намного хуже.
Другая проблема c избыточности заключается в том, что каждый возможный тип аргумента должен быть указан не только в type
, но и в параметре функции. список. Например, (abc: number)
и (abc: string)
в определении типа также требует = (abc: number | string)
в списке параметров.
Существует ли лучший шаблон для перегрузки функции без ее полного отключения? Я знаю как минимум два обходных пути, которые не включают перегрузку:
Передайте объект типа { abc: number, def: string } | { abc: string }
вместо нескольких отдельных параметров, затем передайте объект go через защиту типа
Используйте две отдельные функции для двух разных типов параметров
Но я бы предпочел использовать перегрузку если есть достойный способ справиться с этим.