Search code examples
typescriptmapped-types

How to define mapped type for method return types in typescript 4.5.4?


In typescript 4.4.4 this code compiled fine:

/**
 * type to get only those properties that are functions
 */
type FunctionProperties<T> = {
  [P in keyof T]: T[P] extends (...args: any) => any ? P : never;
}[keyof T];

type ReturnTypeOfMethod<T, K extends FunctionProperties<T>> = ReturnType<T[K]>;

see Playground 4.4.4 example

But the same code fails to compile in typescript 4.5.4 - see Playground 4.5.4 example

Type 'T[K]' does not satisfy the constraint '(...args: any) => any'.
  Type 'T[FunctionProperties<T>]' is not assignable to type '(...args: any) => any'.
    Type 'T[T[keyof T] extends (...args: any) => any ? keyof T : never]' is not assignable to type '(...args: any) => any'.
      Type 'T[keyof T]' is not assignable to type '(...args: any) => any'.
        Type 'T[string] | T[number] | T[symbol]' is not assignable to type '(...args: any) => any'.
          Type 'T[string]' is not assignable to type '(...args: any) => any'.

The strange thing is that the ReturnTypeNumber type still shows the expected type (number in this example).
Any idea why this does not work anymore or how to fix this (using @ts-ignore is not a fix)?


Solution

  • Quite verbose since you have to repeat the condition, but it would suppress the error.

    type ReturnTypeOfMethod<T, K extends FunctionProperties<T>> =
      T[K] extends (...args: any) => any ? ReturnType<T[K]> : never;