Búsqueda de sitios web

reactjs - ¿Cómo llamar a un método de clase dinámicamente con una variable evitando el error 7053 de TypeScript?


Este código se ejecuta correctamente, es decir, ejecuta el método llamado import_codeData en la clase DataIimporter llamando dinámicamente a this.import_codeData() basado en el contenido de la variable de cadena task:

Sin embargo, en Visual Studio Code, TypeScript muestra este error:

Obtiene el mismo error si se envía una cadena simple:

Aunque este código funciona bien, ¿cómo puedo hacer que TypeScript no muestre este error en el editor?


APÉNDICE:

Reproduje este error en línea aquí en 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();

Respuesta #1

Solución en el patio de recreo

El tipo de task necesita ser más específico que solo "string", específicamente keyof DataImporter. Pero cuando haces eso, también puede referirse a claves que nombran no métodos, por lo que necesitarías excluirlos al intentar invocarlos, o como hice yo, comprobar directamente que son funciones.

Tipo de fn:

const fn: "tarea" | "prueba" | "importar_datos001" | (() => void) | (() => void)

Tipo de fn después de considerar solo funciones:

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();

Crédito parcial a https://stackoverflow.com/a/56894533/823470 por ayudar con el primer problema. Resolví el segundo simplemente mirando el tipo inferido de fn y viendo que quería considerar solo funciones.

Respuesta #2

Podrías hacer algo como esto (área de juegos):

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]();
  }
}