Search code examples
typescriptconditional-types

Typescript for "type, or function returning type"


It's useful to allow consumers to provide configuration either as static data, or as a function returning that same schema of data.

Consider some example types:

type T1 = { a: string } | (() => { a: string });
type T2 = { b: boolean, c: number } | (() => { b: boolean, c: number });
type T3 = string[] | (() => string[]);

In general, these types look like:

type T<V> = V | (() => V);

How can I write a type which takes some value in the form of T<V>, and returns V?

I tried:

type ResolveMaybeFunction<T> = ReturnType<T> | T;

But this is no good because ReturnType<T> results in any, so ResolveMaybeFunction<T> always results in any.

Overall, I want the following results:

ResolveMaybeFunction<string | (() => string)>                       === string;
ResolveMaybeFunction<{ a: number[] } | (() => { a: number[] })>     === { a: number[] };
ResolveMaybeFunction<AnyArbitraryType | (() => AnyArbitraryType)>   === AnyArbitraryType;

Solution

  • You need to use a Conditional Type to check if the given type is a function, and then use the return type of the function if it is.

    type ResolveMaybeFunction<T> = T extends ((...args: any) => any) ? ReturnType<T> : T
    

    This says if T is of type function with any number of arguments and has a return value, use the return type of the function. Otherwise, just use the original type

    Playground Link