Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a Typescript object function with a string name

I have a service in my class with multiple functions. The names of the functions come in a string array and I am trying to call them each without much success.

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

This version I get the error:

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

If I try with template literal( this.carService[ `${car.name}` ] ):

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

If I directly input the individual function name it does work.

this.carService[ 'Honda' ] // ok

Thanks.

like image 524
Jhonny Avatar asked Feb 27 '26 07:02

Jhonny


1 Answers

If carService is defined as an object literal, it will lack an index signature (i.e. what to use as the result of an arbitrary string lookup). TypeScript doesn't know that your keys have a special meaning in the context of the object so it is most likely not able to infer that the result of the lookup might be a function.

When I do something similar locally, I don't get the same complaint though:

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

The complaint I get is: “Element implicitly has an 'any' type because type '{ b: () => void; c: () => void; }' has no index signature.”

There are two ways to fix:

  1. Define your service as a dictionary with an index signature:
        const a: { [functionName: string]: Function } = { b: () => {}, c: () => {}};
        const x = ["b", "c"];
        x.forEach(functionName => (a[functionName])());
  1. Explicitly define the incoming list of keys as being valid keys for the object:
        const a = { b: () => {}, c: () => {}};
        const x = ["b", "c"] as (keyof typeof a)[];
        x.forEach(functionName => (a[functionName])());

Which is preferable depends on how exactly you want to use the service and the key list.

like image 81
Mattias Martens Avatar answered Mar 01 '26 21:03

Mattias Martens