title: Typescript: typed access to class functions by index
body: <p>I need to call the functions of the <code>ExampleOne</code> class based on the names of the fields of the <code>DataValues</code> class, taking values from there and passing them to the functions of an instance of the <code>ExampleOne</code> class</p>
  <p>Tell me how to correctly write a function call through the indexer, as you can see there is some problem with the types</p>
  <pre class="lang-js prettyprint-override"><code>class ExampleOne {
      f1(argStr: string): string {
          return `some text ${argStr}`;
      }
      f2(argNumber: number): string {
          return  `some text ${argNumber}`;
      }
  }
  
  class DataValues {
      f1: number = 64;
      f2: string = 'Hello';
  }
  
  function example() {
      const testClass = new ExampleOne();
      const data = new DataValues();
  
      for (const [key, value] of Object.entries(data)) {
          const functionName = key as keyof ExampleOne;
          const func = testClass[functionName];
  
          const arg: number | string = value;
  
  
          const result = func.apply(testClass, [arg]); 
  /*                       | &lt;---------- error this*
                           |
                           |
  The 'this' context of type 
  '((argStr: string) =&gt; string) | ((argNumber: number) =&gt; string)' 
  is not assignable to method's 'this' of type 
  '(this: ExampleOne, argStr: string) =&gt; string'.
  Type '(argNumber: number) =&gt; string' is not assignable to type 
  '(this: ExampleOne, argStr: string) =&gt; string'.
  Types of parameters 'argNumber' and 'argStr' are incompatible.
  Type 'string' is not assignable to type 'number'.(2684) */
  
      console.log(result);
      }
  }
  
  example();
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?#code/FDDGBsEMGdoAgKIA9IFsAO4CmB5AdlnAN7ACQAZgIwAUkATgOYDKALnQFxzRsCWeDASk7c6fBsTKk6WFgFc6eOAANoAe1SEWWJCzgASIvWZsAvkoDcZE2XIAmWowBys1ACMsHOHhfu6Qrrz8EqRSMvKKymoacFo6+oZOPh5mlqTW1mBQsHAAIpAskABqkOCyWPAkFJSc3m4ecAC8cABsACypdsKB4k0A5AASWODgqr2WGeSyeKAsPKqK2miYWNQCwaDz3DHlLADCWfBNBADuiCgY2PgrApZkG3hbACb5kI1eWKd5BcWl5au3FFUdDg1HuWwA2gBrLAATwANHAAG4lMoAXTgqnIcBwrgAVlgZgA6LB4Xh-Z4FARrSqkMG6SbTWbzRxoQhNaEwuAwOAczFnJaXAipWmbelTUBvLTcfYwaDghkzOZ4FkaVEAkUPXRGGpJYEAHwCoiCTWRv3VdLg0mgsnAuiaCsJkHQmBh1ClewOCPBRlRNxAcADcDBqmwhJGDGoVptLD9aWAGUWF2u5iAA" rel="nofollow noreferrer">Playground link</a></p>
  <p>Initially I tried to do this but it didn't work:</p>
  <pre class="lang-js prettyprint-override"><code>    for (const [key, value] of Object.entries(data)) {
          const functionName = key as keyof ExampleOne;
          const func = testClass[functionName];
  
          const arg: number | string = value;
  
          const result = testClass[functionName](arg);
  /*                                              | &lt;--- error this
                                                  |
                                                  |
  Argument of type 'string | number' is not assignable to parameter of type 'never'.
    Type 'string' is not assignable to type 'never'.(2345)
  */
  
      console.log(result);
      }
  </code></pre>