[FIXED] Why is the infer keyword needed in Typescript?

Issue

Why did the Typescript folks create the infer keyword?
According to the documents, this is an example of how you would use it:

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

I don’t understand why this is needed. Why can’t it just be:

type ReturnType<T> = T extends (...args: any[]) => R ? R : any;

Why doesn’t this work? Why is the infer keyword necessary ?

Solution

With infer, the compiler ensures that you have declared all type variables explicitly:

type MyType<T> = T extends infer R ? R : never;
type T1 = MyType<{b: string}> // T1 is { b: string; }

Here we declare a new type variable R in MyType, which gets inferred from T.
(Note, that infer is always used within the extends clause of a conditional type.)

Usage of undeclared type parameters now can result in a compile error:

type MyType2<T> = T extends R2 ? R2 : never; // error, R2 undeclared

Without infer, the compiler wouldn’t know, if you wanted to introduce an additional type variable R2 that is to be inferred (see first case), or if R2 is just an accidental typing error/typo. infer exists to remove this ambiguity.

More precisely the compiler checks, if T is assignable to R , when infer is omitted:

type R = { a: number }
type MyType3<T> = T extends R ? R : never; // compare T with type R
type T2 = MyType2<{b: string}> // T2 is never

Note, that infer R shadows type references of an equally-named type declaration R:

type R = { a: number }
type MyType<T> = T extends infer R ? R : never;
type T1 = MyType<{b: string}> // { b: string; }

Playground

Answered By – ford04

Answer Checked By – Pedro (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published