Xen_mar
Xen_mar

Reputation: 9702

Inferring generics when using extends

Today, I came across this type:

interface Base {
  one: number;
  two: number;
}

export type SelectSubset<T, U> = {
    [key in keyof T]: key extends keyof U ? T[key] : never
}

type TQuestion = <T extends Base>(args: SelectSubset<T, Base>) => void

const example: TQuestion = (obj) => {}

I'm extremely unsure why the type of the generic T can be inferred in this example. I see that T is constrained to Base but would assume that I'd have to pass a default value for the compiler to figure out what T resolves to. I'm assuming that the compiler simply assumes T has the type of Base of no explicit type is passed?

Upvotes: 0

Views: 53

Answers (1)

Chase
Chase

Reputation: 5615

In the snippet you've posted, there's no real inferring needed to be done by the compiler.

In this line-

const example: TQuestion = (obj) => {};

you've merely defined a function of type TQuestion, no inferring needs to be done here. Since no type is explicitly mentioned on the obj parameter, it's picked up from the TQuestion type. This is equivalent to-

function example<T extends Base>(obj: SelectSubset<T, Base>): void {}

If you did-

const example = (obj) => {};

The compiler would complain about obj is missing a type and has an implicit any type (assuming you have the "no implicit any" setting set to true). Here, a type is completely missing, but when you declare example to be of type TQuestion, the function you store in it should be of type TQuestion, which is why the obj parameter automatically gets the type SelectSubset<T, Base>

The actual inferring and type checking of these constraints only come into play once you actually call the function.

Upvotes: 1

Related Questions