Search code examples
typescripttypescript-types

How to use ReturnType on a function that also has a generic


The following code snippet demonstrates the problem:

function foo<T>(init: T) {
    let data = init;
    return {
        getData: () => data,
        update: (u: T) => { data = u }
    }
}

let obj: ReturnType<typeof foo>;

obj = foo<boolean>(true); // ERROR

DEMO

The error is:

Type '{ getData: () => boolean; update: (u: boolean) => void; }' is not assignable to type '{ getData: () => unknown; update: (u: unknown) => void; }'.
  Types of property 'update' are incompatible.
    Type '(u: boolean) => void' is not assignable to type '(u: unknown) => void'.
      Types of parameters 'u' and 'u' are incompatible.
        Type 'unknown' is not assignable to type 'boolean'.

What happens is that in

let obj: ReturnType<typeof foo>;

I don't the define the generic, which makes T -> unknown. So I can fix this as follows

let obj: ReturnType<typeof foo>;

obj = foo<unknown>(true);

So my question is, is it possible to somehow define the generic T in

let obj: ReturnType<typeof foo>;

and set it to, for example, a boolean?


Solution

  • There is a syntax for passing a generic without calling the function itself:

    const func = <T>(arg: T): void => {}
    
    // (arg: boolean) => void
    const booleanFunc = func<boolean>
    
    // (arg: string) => void
    const stringFunc = func<string>
    

    You can apply the same syntax to get the return type:

    ReturnType<typeof foo<boolean>>