【发布时间】:2019-03-08 16:28:36
【问题描述】:
我有以下函数调用:
this.get('barcode').scan();
是否可以以返回类型由函数参数的值确定的方式定义 get 函数。在我的例子中,如果使用 'barcode' 调用,'get' 返回 Barcode 类,如果使用 'mqtt' 调用,则返回 Mqtt 类。
【问题讨论】:
标签: typescript
我有以下函数调用:
this.get('barcode').scan();
是否可以以返回类型由函数参数的值确定的方式定义 get 函数。在我的例子中,如果使用 'barcode' 调用,'get' 返回 Barcode 类,如果使用 'mqtt' 调用,则返回 Mqtt 类。
【问题讨论】:
标签: typescript
是的,您可以使用 字符串重载 来执行此操作。示例:
interface BarcodeScanner { scan(): number; }
interface Accelerometer { getAcceleration(): number; }
class MyClass {
get(name: 'accelerometer'): Accelerometer;
get(name: 'barcode'): BarcodeScanner;
get(name: string): any; // Fallback string signature
get(name: string): any { // Implementation signature, not visible
/* ... */
return undefined;
}
something() {
let x = this.get('barcode');
x.scan(); // OK
let y = this.get('accelerometer');
y.getAcceleration(); // OK
}
}
【讨论】:
不可能在(动态)字符串的函数中静态确定类型。但是generics 是为这些情况而设计的。
例子:
class MyClass {
public get<T>(type: string): T {
// ...
}
public anotherMethod() {
this.get<Barcode>('barcode').scan();
}
}
我不确定是否理解 Ember 的问题,但如果 get 方法是动态插入到对象中的,那么可能是这样的解决方案:
class MyClass {
public get: function<T> (type: string): T; // this is just a static declaration, there is no generated JS code here
public anotherMethod() {
this.get<Barcode>('barcode').scan();
}
}
【讨论】:
declare 或使用接口来描述类型 Barcode。
是的,从 Typescript 3.2 开始,您可以使用条件类型来解决问题:
const get = <T extends "barcode" | "mqtt">(s: T) =>
s === "barcode" ?
<T extends "barcode" ? {scan: () => string} : {pan: () => string}>{scan: () => "we are scanning"} :
<T extends "barcode" ? {scan: () => string} : {pan: () => string}>{pan: () => "we are panning"}
get("barcode").scan() // OK
get("mqtt").pan() // OK
get("barcode").pan() // Error
注意:我没有成功地将强制转换移动到函数的返回类型 - 这将不得不为真正的专家提出另一个问题。
【讨论】: