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 ?
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; }
R
in MyType
, which gets inferred from T
.infer
is only used within the extends
clause of a conditional type.Without infer
, the compiler does not introduce an additional type variable R2
that is to be inferred (see first case). If R2
has not been declared, it will result in a compile error:
type MyType2<T> = T extends R2 ? R2 : never; // error, R2 undeclared
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 T3 = MyType3<{b: string}> // T3 is never
Note, that infer R
shadows type references of an equally-named type declaration R
:
type R = { a: number }
type MyType4<T> = T extends infer R ? R : never;
type T4 = MyType4<{b: string}> // { b: string; }