TypeScript:如何获取和使用具有多个声明的类方法的类型
无法比标题中的内容更好地解释它,因此下面是一个示例:TypeScript:如何获取和使用具有多个声明的类方法的类型,typescript,Typescript,无法比标题中的内容更好地解释它,因此下面是一个示例: declare class myClass { myMethod(num: number): number; // declaration 1 myMethod(str: string, num: number): number; // declaration 2 } let func1: myClass['myMethod'] = (num: number) => 0; let func2: myClass['myMeth
declare class myClass {
myMethod(num: number): number; // declaration 1
myMethod(str: string, num: number): number; // declaration 2
}
let func1: myClass['myMethod'] = (num: number) => 0;
let func2: myClass['myMethod'] = (str: string, num: number) => 0;
上面的代码未编译,输出以下错误:
error TS2322: Type '(num: number) => number' is not assignable to type '{ (num: number): number; (str: string, num: number): number; }'.
Types of parameters 'num' and 'str' are incompatible.
Type 'string' is not assignable to type 'number'.
error TS2322: Type '(str: string, num: number) => number' is not assignable to type '{ (num: number): number; (str: string, num: number): number; }'.
如果我对以下任何一项进行评论:
- 声明1和功能1或
- 宣言2和宣言2
同一方法的多个声明在某些开源软件包的声明文件中非常常见,例如,
aws sdk
多个函数或方法声明描述了。重载函数或方法具有一个或多个调用签名,这些签名是类型声明的一部分。您可以将这组调用签名表示为接口/类/作用域中的重复函数/方法/可调用签名,或者表示为所有调用签名的集合。重载函数必须能够以调用签名描述的每种方式调用
当您实现一个重载函数或方法时,您使用一个从外部看不到的实现签名。。。这是函数的一个实现细节。但是实现签名需要能够处理所有的调用签名。如果不能,你就有问题了
我将把您的代码重写为单个重载函数接口MyMethod
:
interface MyMethod {
(num: number): number; // declaration 1
(str: string, num: number): number; // declaration 2
}
let func1: MyMethod = (num: number) => 0; // error
let func2: MyMethod = (str: string, num: number) => 0; // error
这与您的代码基本相同,并且存在相同的问题func1
不是有效的MyMethod
。您只能调用func1(123)
,但不能调用func1(“abc”,123)
。但是MyMethod
必须支持这两个调用。类似地,func2
只支持第二个调用签名,而不支持第一个
现在考虑一下:
let funcBoth: MyMethod = (strOrNum: string | number, num?: number) => 0; // okay
这个编译得很好。这是因为funcall
的实现签名可以支持调用likefuncall(123)
和likefuncall(“abc”,123)
:
现在,实现签名也支持像funcall(123456)
那样调用,但是funcall
作为MyMethod
的注释不允许这样做:
funcBoth(123, 456); // error! bad first argument
因此,实现签名对调用方是隐藏的,因此在函数实现中,您可以安全地依赖调用方不会传入意外参数这一事实
如果需要调用
func1
或func2
的行为,这取决于调用funcBoth
的方式,则必须通过检查参数自行进行分派:
let f1 = (num: number) => 0;
let f2 = (str: string, num: number) => 0;
let f12: MyMethod = (strOrNum: string | number, num?: number) =>
typeof strOrNum === "number" ? f1(strOrNum) : f2(strOrNum, num!);
好吧,希望这会有帮助;祝你好运
惊人的答案。谢谢
let f1 = (num: number) => 0;
let f2 = (str: string, num: number) => 0;
let f12: MyMethod = (strOrNum: string | number, num?: number) =>
typeof strOrNum === "number" ? f1(strOrNum) : f2(strOrNum, num!);