Учитывая, что ваша перегруженная инструкция функции hello
, вы можете обнаружить тип, который компилятор для него сам выводит, записав псевдоним типа в его тип и проверяя его с помощью IntelliSense при наведении поверх него в вашей IDE:
type Hello = typeof hello;
/* type Hello = {
(name: number): void;
(name: string): void;
} */
Здесь вы можете видеть, что Hello
считается типом объекта с двумя сигнатурами вызовов , представляющими сигнатуры вызовов, которые вы объявили в своей перегрузке список в том же порядке.
Вы также можете написать эквивалентный тип как пересечение типов функций:
type AlsoHello = ((name: string) => void) & ((name: number) => void);
Если у вас есть типы функций F1
и F2
, затем F1 & F2
представляет перегруженную функцию, где подпись F1
проверяется перед подписью F2
. В (все более и более устаревшем) TypeScript spe c говорится:
Хотя обычно верно, что A & B
эквивалентен B & A
, порядок составляющих типы могут иметь значение при определении вызова и создания сигнатур типа пересечения.
В остальной части ответа я буду использовать версию object-type-with-множественные call-подписи вместо версия пересечения стрелки-функции-подписи.
В любом случае, в этом конкретном случае, когда обе подписи возвращают void
, вы можете переписать hello
как const
без ошибок, если вы аннотируете его указанным выше типом:
const helloConst: {
(name: number): void;
(name: string): void;
} = (name: number | string): void => {
// ...
}
В общем, предостережение, хотя ... перегруженные операторы не проверяются так строго, как const
назначение. Перегруженные операторы функций позволяют типу возврата сигнатуры реализации соответствовать объединению типов возврата сигнатур вызовов, даже если это небезопасно:
function goodbye(name: number): number;
function goodbye(name: string): string;
function goodbye(name: number | string): number | string {
return typeof name === "number" ? name + 1 : name + "!";
}
В приведенном выше нет ошибки компилятора. Реализация goodbye()
возвращает number | string
, и вы можете изменить typeof name === "number"
на typeof name !== "number"
, и компилятор все равно не предупредит вас. Обычно это считается функцией, а не ошибкой.
Но теперь, если вы написали это как const
, вы получите ошибку:
const goodbyeConst: { // error!
(name: number): number;
(name: string): string;
} = (name: number | string): number | string =>
typeof name === "number" ? name + 1 : name + "!";
// Type '(name: string | number) => string | number'
// is not assignable to
// type '{ (name: number): number; (name: string): string; }'.
Назначение const
проверено более строго, и компилятор (правильно) жалуется, что вы не можете безопасно обрабатывать функцию типа (name: string | number) => string | number
как функцию типа ((name: string) => string) & ((name: number) => number)
. В конце концов, реализация всегда может вернуть string
, который соответствует сигнатуре реализации, но не соответствует сигнатуре вызова number
.
В любом случае, в таком случае можно использовать тип утверждение вместо аннотации:
const goodbyeConstAssert = ((name: number | string): number | string =>
typeof name === "number" ? name + 1 : name + "!") as { // error!
(name: number): number;
(name: string): string;
}
Это компилируется без ошибок.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код