如何在打字稿中为 const 定义重载签名?
How to define overloaded signatures for a const in typescript?
我们可以在打字稿中这样定义重载函数:
function hello(name: number): void;
function hello(name: string): void;
function hello(name: number | string): void {
// ...
}
我试图将此函数定义为常量,例如:
const hello = (name: number | string): void => {
// ...
}
但不确定如何在其上声明重载签名:
(name: number): void;
(name: string): void;
请帮忙,谢谢
您可以使用可调用签名定义 type/interface 并使用它来键入变量:
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)
将您的 overloaded function statement hello
, you can discover the type that the compiler infers for it yourself by writing a 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 它说:
While it is generally true that A & B
is equivalent to B & A
, the order of the constituent types may matter when determining the call and construct signatures of the intersection type.
在其余的答案中,我将使用带有多个调用签名的对象类型版本,而不是箭头函数签名交集版本。
无论如何,在这种 特殊的 情况下,两个签名 return void
,您可以将 hello
重写为 const
如果你 annotate 上面的类型没有错误:
const helloConst: {
(name: number): void;
(name: string): void;
} = (name: number | string): void => {
// ...
}
一般来说,虽然...重载函数语句的检查不像 const
赋值那样严格。重载函数语句允许实现签名的 return 类型匹配调用签名的 return 类型的联合,即使这不安全:
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()
returns 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)
的函数.毕竟,实现总是可以 return 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;
}
编译没有错误。
好的,希望对您有所帮助;祝你好运!
我们可以在打字稿中这样定义重载函数:
function hello(name: number): void;
function hello(name: string): void;
function hello(name: number | string): void {
// ...
}
我试图将此函数定义为常量,例如:
const hello = (name: number | string): void => {
// ...
}
但不确定如何在其上声明重载签名:
(name: number): void;
(name: string): void;
请帮忙,谢谢
您可以使用可调用签名定义 type/interface 并使用它来键入变量:
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)
将您的 overloaded function statement hello
, you can discover the type that the compiler infers for it yourself by writing a 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 它说:
While it is generally true that
A & B
is equivalent toB & A
, the order of the constituent types may matter when determining the call and construct signatures of the intersection type.
在其余的答案中,我将使用带有多个调用签名的对象类型版本,而不是箭头函数签名交集版本。
无论如何,在这种 特殊的 情况下,两个签名 return void
,您可以将 hello
重写为 const
如果你 annotate 上面的类型没有错误:
const helloConst: {
(name: number): void;
(name: string): void;
} = (name: number | string): void => {
// ...
}
一般来说,虽然...重载函数语句的检查不像 const
赋值那样严格。重载函数语句允许实现签名的 return 类型匹配调用签名的 return 类型的联合,即使这不安全:
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()
returns 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)
的函数.毕竟,实现总是可以 return 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;
}
编译没有错误。
好的,希望对您有所帮助;祝你好运!