我们可以在打字稿中定义像这样的重载函数:
function hello(name: number): void;
function hello(name: string): void;
function hello(name: number | string): void {
// ...
}
我试图将此函数定义为const,例如:
const hello = (name: number | string): void => {
// ...
}
但不确定如何在其上声明过载签名:
(name: number): void;
(name: string): void;
请帮助,谢谢
鉴于您的overloaded函数语句hello
,您可以通过将type alias写入其类型并通过将其悬停在IDE中并通过IntelliSense进行检查来发现编译器自己为其推断的类型:
type Hello = typeof hello;
/* type Hello = {
(name: number): void;
(name: string): void;
} */
在这里您可以看到Hello
被认为是具有两个call signatures的对象类型,它们代表您在过载列表中以相同顺序声明的呼叫签名。
您还可以将等效类型写为功能类型的intersection:
type AlsoHello = ((name: string) => void) & ((name: number) => void);
[如果您具有F1
和F2
功能类型,则F1 & F2
表示重载功能,其中在F1
签名之前先检查F2
签名。在(越来越过时的)TypeScript spec中,它说:
虽然
A & B
等同于B & A
通常是正确的,但是在确定调用并构造交叉点类型的签名时,构成类型的顺序可能很重要。
在其余的答案中,我将使用带有多个调用签名的对象类型版本,而不是使用箭头功能签名的交集版本。
无论如何,在这两个签名都返回void
的特殊情况下,如果使用上述类型的hello
,则可以将其const
重写为annotate,没有错误:
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
。
无论如何,在这种情况下,要使用type assertion而不是注释:
const goodbyeConstAssert = ((name: number | string): number | string =>
typeof name === "number" ? name + 1 : name + "!") as { // error!
(name: number): number;
(name: string): string;
}
该编译没有错误。
好的,希望能有所帮助;祝你好运!
您可以使用可调用的签名定义类型/接口,并使用它来键入变量:
type Hello = {
(name: number): void,
(name: string): void,
}
const hello: Hello = (name: number | string): void => {
// ...
}
hello(1); // ok
hello('1'); // ok
declare const wrong: string | number;
// @ts-expect-error
hello(wrong)