๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

TypeScript Infer Basics

The infer keyword declares a new type variable inside the check of a conditional type. The checker fills that variable with the type it finds in the matching position.

Infer reads an array element type

ElementOf places infer inside an array pattern. The variable U takes the element type of the array that matches.

type ElementOf<T> = T extends (infer U)[] ? U : T;
type Item = ElementOf<string[]>;
const item: Item = 'pen';
console.log(item);

A home-grown MyReturnType

MyReturnType places infer in the return position of a function pattern. The intermediate course used the built-in ReturnType for this job, and the home-grown version computes the same type.

function greet(who: string): string {
  return 'Hello, ' + who;
}
type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
type GreetResult = MyReturnType<typeof greet>;
type BuiltInResult = ReturnType<typeof greet>;
const a: GreetResult = 'Hello, Ada';
const b: BuiltInResult = 'Welcome';
console.log(a);
console.log(b);

A failed match takes the false branch

A plain string is not a function, so the function pattern cannot match. Infer binds nothing and the false branch names the result.

type ReturnOf<F> = F extends (...args: any[]) => infer R ? R : 'not a function';
type Bad = ReturnOf<string>;
const bad: Bad = 'not a function';
console.log(bad);

Example

function loadTags(): string[] {
  return ['new', 'sale'];
}
type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;
type ElementOf<T> = T extends (infer U)[] ? U : T;
type TagList = MyReturnType<typeof loadTags>;
type Tag = ElementOf<TagList>;
const tags: TagList = ['hot', 'new'];
const tag: Tag = 'hot';
console.log(tags.join(', '));
console.log(tag);

Key points

  • An infer declaration sits inside the extends part of a conditional check.
  • The declared variable exists only inside that conditional type.
  • A match binds the variable to the type found at the infer position.
  • A failed match binds nothing, and the false branch supplies the result.
  • Infer powers the built-in reading utilities, and this lesson builds one of them by hand.

In this example, MyReturnType reads the array type that loadTags returns, and ElementOf then reads the element type out of that array type.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท TypeScript Playground

Exercise

What does infer declare inside a conditional type check?