Skip to content
webtype.orgTwelve concepts · 7/12

Concept 7 of 12

infer

`infer` is pattern matching. You describe the shape you expect, put `infer X` where the interesting part sits, and the compiler solves for `X`. Most of the standard library’s extraction helpers are one conditional with one `infer` in the right place.

It works anywhere a type can appear

type Unwrap<T> = T extends Promise<infer Inner> ? Inner : T
type Element<T> = T extends (infer E)[] ? E : never
type Returns<T> = T extends (...a: never[]) => infer R ? R : never
type Head<T> = T extends [infer H, ...unknown[]] ? H : never
type Rest<S> = S extends `${string}-${infer R}` ? R : never

Promises, arrays, function returns, tuple positions, string patterns — the mechanism is identical every time. Only the surrounding shape changes, which is why learning one of these teaches you all of them.

Constraining what gets bound

// Without the constraint, F is unknown and cannot be
// interpolated into a template literal.
type First<T> = T extends [infer F extends string, ...unknown[]]
  ? `${F}!`
  : never

An `infer` can carry its own `extends` clause, which narrows what it binds and lets you use the result where a specific kind of type is required. Without it you often get `unknown`, and the error appears one line later than the cause.

The common wrong answer

// Intent: get the return type of any function.
type Returns<T> = T extends () => infer R ? R : never

Returns<() => string>          // string
Returns<(a: number) => string> // never — pattern demands zero parameters

// Fixed: never[] in parameter position accepts any signature,
// because parameters are checked contravariantly.
type Returns2<T> = T extends (...a: never[]) => infer R ? R : never

The pattern has to be as permissive as the inputs you want to match. A zero-parameter function type only matches zero-parameter functions, so everything else silently falls into the false branch.

Takeaway

Describe the shape, mark the hole with `infer`, and let the compiler fill it. If nothing matches, the pattern is stricter than the input — not the other way round.

Practiced in