Conditional types

Types chosen based on a condition: T extends U ? X : Y.

On this page

Example

#
TypeScript
type Label<T> = T extends string ? 'text' : T extends number ? 'number' : 'something else'

type A = Label<'html'>
// type A = "text"
type B = Label<42>
// type B = "number"
type C = Label<boolean>
// type C = "something else"

type OnlyStrings<T> = T extends string ? T : never
type Mixed = OnlyStrings<'a' | 1 | 'b' | true>
// type Mixed = "a" | "b"

Definition and usage

#

A conditional type works like the ternary operator, but on types: T extends string ? "text" : "other". If T is assignable to string, the result is the first type, otherwise the second.

When T is a union, the condition is applied to each of its members separately (this is called distribution). This makes it easy to filter unwanted types out of a union by returning never for them. That’s how the built-in Exclude and Extract work.

Conditional types are the foundation of many utility types and libraries. They show up less often in application code, but it’s worth understanding them in order to read type definitions.

Syntax

#
Syntax
type Result<T> = T extends Condition ? TypeIfTrue : TypeIfFalse

More examples

#
A type that depends on an argument
TypeScript
function parse<T extends 'number' | 'boolean'>(value: string, as: T): T extends 'number' ? number : boolean {
  return (as === 'number' ? Number(value) : value === 'true') as T extends 'number' ? number : boolean
}

console.log(parse('42', 'number') + 1)
console.log(parse('true', 'boolean'))
Result
43
true

Good practices

#
  • If a conditional type starts getting long, break it up into several named helper types.
  • Distribution over a union can be turned off by wrapping the type in square brackets: [T] extends [string].

Related entries

#

Spotted a mistake or missing an example? Write to us.