Search code examples
typescriptgenericsinferencetype-inference

Possible to infer type used within a generic interface of a parameter?


I have this method:

attachTheme<TTheme, TSelector>(config: IConfig<TTheme, TSelector>): OtherClass<TSelector> {
}

IConfig:

interface IConfig<TTheme, TSelector> {
    select(theme: TTheme): TSelector;
}

I would like to use it in this way:

attachTheme<MyTheme>({ select: theme => ({ background: theme.scroller.background }) });

With the return value being typed with { background: string; } but if I don't specify the TSelector with a default, it complains, so if I put {} as a default, the outputted generic type is {}, even though I feel it should infer the type.

I've looked into the infer keyword, but can't get it to work, I feel like I don't understand it well enough to use it in the right way and I was hoping someone would understand it better than I enough to solve my issue? There seems to be very little about the keyword and fewer examples of how it can be used.


Solution

  • The simplest solution is to let the compiler infer both parameters by specifying the theme as a type annotation to the arrow function parameter

    attachTheme({ select: (theme: MyTheme) => ({ background: theme.scroller.background }) });
    

    If you don't want to do this in 3.1 we will get Named type arguments & partial type argument inference

    The other solution is to use a function returning a function to be able to specify one argument and lent inference take care of the other one .

    function attachTheme<TTheme>() {
        return function <TSelector>(config: IConfig<TTheme, TSelector>): OtherClass<TSelector> {
            return null;
        }
    }
    
    attachTheme<MyTheme>()({ select: theme => ({ background: theme.scroller.background }) });