【问题标题】:Typescript: declare return type to be dependent on argument value?打字稿:声明返回类型依赖于参数值?
【发布时间】:2019-03-08 16:28:36
【问题描述】:

我有以下函数调用:

this.get('barcode').scan();

是否可以以返回类型由函数参数的值确定的方式定义 get 函数。在我的例子中,如果使用 'barcode' 调用,'get' 返回 Barcode 类,如果使用 'mqtt' 调用,则返回 Mqtt 类。

【问题讨论】:

标签: typescript


【解决方案1】:

是的,您可以使用 字符串重载 来执行此操作。示例:

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
    }
}

【讨论】:

    【解决方案2】:

    不可能在(动态)字符串的函数中静态确定类型。但是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();
        }
    }
    

    【讨论】:

    • 问题是我必须将类型声明改造成现有的 JavaScript 库。
    • 因此,您可以从现有的 JavaScript 库 with the keyword declare 或使用接口来描述类型 Barcode
    • 看来我误解了这个问题。问题是我还没有想出让 TypeScript 接受 get 声明(我得到 Property 'get' is missing in type)。这是真的,因为它来自 Ember 框架。
    • 也许你可以尝试使用the ember definition
    【解决方案3】:

    是的,从 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
    

    注意:我没有成功地将强制转换移动到函数的返回类型 - 这将不得不为真正的专家提出另一个问题。

    【讨论】:

    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 2020-11-07
    相关资源
    最近更新 更多