【问题标题】:How to call class method dynamically with variable while avoiding TypeScript error 7053?如何在避免 TypeScript 错误 7053 的同时使用变量动态调用类方法?
【发布时间】:2020-10-29 12:07:57
【问题描述】:

这段代码运行良好,即通过基于字符串变量task的内容动态调用this.import_codeData(),在类DataIimporter上执行名为import_codeData的方法:

但是,在 Visual Studio Code 中,TypeScript 显示此错误:

如果发送一个简单的字符串,它会得到同样的错误:

虽然此代码运行良好,但如何让 TypeScript 不在编辑器中显示此错误?


附录:

我在TypeScript Playground 在线复制了这个错误:

class DataImporter {

    task: string;

    constructor() {
        this.task = "import_data001";
    }

    test() {
        this[this.task]();
    }

    import_data001() {
        console.log('importing data001');
    }
}

const dataImporter = new DataImporter();
dataImporter.import_data001();
dataImporter.test();

【问题讨论】:

标签: reactjs typescript


【解决方案1】:

Solution on the playground

task 的类型需要比“字符串”更具体,特别是keyof DataImporter。但是当你这样做时,它也可以引用命名非方法的键,所以你需要在尝试调用它们时排除它们,或者像我一样,直接检查它们是否是函数。

fn 的类型:

const fn: "任务" | “测试” | "import_data001" | (() => 无效) | (() => 无效)

只考虑功能后fn的类型:

const fn: () => void


class DataImporter {

    task: keyof DataImporter;

    constructor() {
        this.task = "import_data001";
    }

    test() {
        const fn = this[this.task];
        if (typeof fn === 'function') { // or !== 'string'
            fn();
        }
    }

    import_data001() {
        console.log('importing data001');
    }
}

const dataImporter = new DataImporter();
dataImporter.import_data001();
dataImporter.test();

部分归功于 https://stackoverflow.com/a/56894533/823470 对第一个问题的帮助。我通过查看fn 的推断类型并看到我只想考虑函数来解决了第二个问题。

【讨论】:

    【解决方案2】:

    你可以这样做(playground):

    type GetLength<T extends any[]> = T extends { length: infer L } ? L : never
    
    type ZeroLength<T> = {
      [K in keyof T]: T[K] extends () => void  ? (GetLength<Parameters<T[K]>> extends 0 ? K : never): never;
    }[keyof T]
    
    type Callable = ZeroLength<Foo>
    
    class Foo {
      doA() {
    
      }
    
      doB() {
    
      }
    
      doC() {
    
      }
    
      multipleArgs(a: number, b: number) {
        return a + b;
      }
    
      runSomething(fnName: Callable) {
        this[fnName]();
      }
    }
    

    【讨论】:

    【解决方案3】:
    test() {
            (this[this.task as keyof DataImporter] as Function)();
    }
    
    • 我们将 keyof 运算符应用于 this.task,从而告诉编译器它是 this.task表示 DataImporter 类的属性
    • 我们将 Function 应用到 this[this.task as keyof DataImporter] 从而断言它是一个Function

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      相关资源
      最近更新 更多