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['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和func1或
  • 声明2和func2,

编译成功。

在某些开源软件包的声明文件中,经常会发生同一方法的多次声明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

这样编译就可以了。这是因为的实现签名funcBoth可以支持likefuncBoth(123) like的调用funcBoth("abc", 123)

funcBoth(123); // okay
funcBoth("abc", 123); // okay

现在,实现签名也将支持被称为like funcBoth(123, 456),但是funcBothas的注释MyMethod不允许您这样做:

funcBoth(123, 456); // error! bad first argument  

因此,实现签名对调用者是隐藏的,因此在函数实现内部,您可以放心地依靠调用者不会传入意外参数这一事实。


如果您想要调用的行为func1func2取决于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!);

好吧,希望能有所帮助;祝好运!

链接到代码

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何声明具有多个界限的类类型的对象

获取错误:目标类必须声明具有匹配名称和参数类型的方法

在TypeScript中,如何获取具有多个类型参数的方法中的泛型类型参数?

使用Prism 7的WPF App:如何使用具有多个具体类的接口为VM注册和导航

如何从具有函数依赖项的类型类中获取和使用依赖项类型?

如何在同一类上使用具有相同名称的静态方法和实例方法?

如何在具有泛型参数和返回类型方法的Java中使用反射获取类的实例?

使用具有基于类的视图和分页的多个模型

如何引用具有多个界限的通用返回类型

在 Typescript 中使用具有联合类型的 Mixin

如何在目标C中使用具有通用类型的Swift类

如何在 Electron 上使用具有 TypeScript 类型支持的内部函数或条件?

如何在TypeScript中使用具有接口联合类型的实例?

如何使用具有内容类型文本/纯文本的PHP获取外部JSON?

如何使用具有多个ID的单个字段获取价值?

使用反射获取具有原始类型参数的类的方法

如何使用具有多个具有不同标题的记录类型的Filehelpers附加到CSV文件?

声明具有相同类型的多个TypeScript变量

声明具有相同类型的多个TypeScript变量

使用具有多个视图和小模型的主干

使用具有多个证书和私钥的PEM文件

如何使用具有CLP(FD)和多个约束的DCG枚举组合

在 Postgresql 中,如何使用具有多个条件的连接,包括 >= 和 <=

如何在 Laravel 中使用具有不同页面和路由的多个域?

如何使用 RxJs 以并行方式调用具有多个和可取消请求的后端?

使用python cx_Oracle,如何调用具有多个声明的DBMS_METADATA.SET_TRANSFORM_PARAM?

如何调用具有多个线程的方法

不确定如何使用具有变量的集合返回类型调用方法

如何使用不带约束的类型参数调用具有泛型约束的方法?