angular - Apelarea unei funcții dintr-un obiect Typescript folosind un nume de tip șir


Am un serviciu în clasa mea cu mai multe funcții. Numele funcțiilor vin într-un array de stringuri și încerc să le apelez pe fiecare fără prea mult succes.

cars.forEach( car => {
    this.carService[ car.name ](
        height,
        plateNr
    );
} );

În această versiune primesc eroarea:

ERROR TypeError: _this.carService[car.name] is not a function

Dacă încerc cu literal de șablon (this.carService[`${car.name}`]):

ERROR TypeError: _this.carService[("" + car.name)] is not a function

Dacă introduc direct numele funcției individuale, funcționează.

this.carService[ 'Honda' ]/ok

Mulțumesc.

Răspuns #1

Dacă carService este definit ca un literal de obiect, va lipsi o semnătură de index (adică ce să se folosească ca rezultat al unei căutări arbitrare după șir). TypeScript nu știe că cheile tale au un înțeles special în contextul obiectului, așa că cel mai probabil nu poate deduce că rezultatul căutării ar putea fi o funcție.

Când fac ceva similar local, totuși nu primesc aceeași plângere:

        const a = { b: () => {}, c: () => {}};
        const x = ["b", "c"];
        x.forEach(functionName => (a[functionName])());

Plângerea pe care o primesc este: „Elementul are implicit un tip 'any' deoarece tipul '{ b:() => void; c:() => void; }' nu are o semnătură de index.”

Există două moduri de a remedia:

  1. Definește serviciul tău ca un dicționar cu o semnătură de index:
        const a: { [functionName: string]: Function } = { b: () => {}, c: () => {}};
        const x = ["b", "c"];
        x.forEach(functionName => (a[functionName])());
  1. Definește explicit lista de chei primite ca fiind chei valide pentru obiect:
        const a = { b: () => {}, c: () => {}};
        const x = ["b", "c"] as (keyof typeof a)[];
        x.forEach(functionName => (a[functionName])());

Ceea ce este de preferat depinde de modul exact în care doriți să utilizați serviciul și lista de chei.

Răspunsul #2

Încearcă asta, funcționează bine

cars.forEach( car =>
     { 
let carName = car.name;
    this.carService[ carName ]( height, plateNr ); 
} );