Skip to main content

What is a "conditional type"?

What a Conditional Type is

A Conditional Type has the general form:

javascript
T extends U ? X : Y

This reads as:

"If type T is assignable to type U, then the result is type X, otherwise it is type Y."


The simplest example

javascript
type IsString<T> = T extends string ? "yes" : "no"; type A = IsString<string>; // "yes" type B = IsString<number>; // "no"

How it works

  • extends in the context of a conditional type is not "inheritance" but a type compatibility check;
  • the condition is evaluated at compile time;
  • the result is another type.

Example with real types

javascript
type ElementType<T> = T extends (infer U)[] ? U : T; type A = ElementType<string[]>; // string type B = ElementType<number[]>; // number type C = ElementType<boolean>; // boolean

This uses infer U, an operator for extracting a subtype.


Using it with generics

Conditional types are especially powerful in generics:

javascript
type Response<T> = T extends Error ? "Failed" : "Success"; type A = Response<string>; // "Success" type B = Response<Error>; // "Failed"

Example: filtering types

javascript
type NonNullable<T> = T extends null | undefined ? never : T; type A = NonNullable<string | null | undefined>; // string

This is the actual implementation of the built-in NonNullable.


Distributive behavior

Conditional types behave differently when T is a union.

If T is a union (A | B), TypeScript distributes the condition over each member:

javascript
type ToArray<T> = T extends any ? T[] : never; type R = ToArray<string | number>; // (string | number) distributes -> string[] | number[]

That is:

javascript
ToArray<string | number> ≡ ToArray<string> | ToArray<number>

This is called a distributive conditional type.


To turn off distribution

You can wrap the type in a tuple to "remove" the distributivity:

javascript
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never; type R = ToArrayNonDist<string | number>; // (string | number)[]

Examples from the standard library

Many built-in utilities are built on conditional types:

UtilityImplementationWhat it does
Exclude<T, U>T extends U ? never : TRemoves from T everything assignable to U
Extract<T, U>T extends U ? T : neverKeeps only the intersection of T and U
NonNullable<T>T extends null | undefined ? never : TRemoves null and undefined
ReturnType<T>T extends (...args:any) => infer R ? R : anyExtracts the return value's type
InstanceType<T>T extends new (...args:any) => infer R ? R : anyExtracts the type of the created instance

Practical examples

Choosing the return type

javascript
type Result<T> = T extends true ? "OK" : "FAIL"; type A = Result<true>; // "OK" type B = Result<false>; // "FAIL"

Checking whether a type is a function

javascript
type IsFunction<T> = T extends (...args: any[]) => any ? true : false; type A = IsFunction<() => void>; // true type B = IsFunction<number>; // false

Extracting a Promise's result

javascript
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; type A = UnwrapPromise<Promise<string>>; // string type B = UnwrapPromise<number>; // number

Conditional typing of parameters

javascript
type ApiResponse<T> = T extends { error: any } ? { ok: false; error: T["error"] } : { ok: true; data: T }; type A = ApiResponse<{ data: string }>; // { ok: true; data: { data: string } } type B = ApiResponse<{ error: string }>; // { ok: false; error: string }

Key concepts

TermExplanation
extendsChecks type compatibility
inferLets you extract nested types
DistributivityThe conditional type is applied separately to each member of a union
neverUsed to "exclude" values from a union
"Type-level if"Conditional types are a way to describe branching logic at the type level

Summary

ConceptDescription
Conditional typeA type that is chosen depending on another type
SyntaxT extends U ? X : Y
When to useWhen a type depends on the shape/compatibility of another type
Key toolsextends, infer, never
ExamplesExclude, Extract, ReturnType, NonNullable, InstanceType

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.