DevAcademy
LearnTypeScriptConditional Types
AdvancedTypeScript

Conditional Types

Learn how to choose between two types based on a condition, using TypeScript’s extends ? : syntax.

Reading Time

18 min

Lesson

Lesson 24 of 30

What is a Conditional Type?

A conditional type picks between two types based on whether one type is assignable to another, using syntax that mirrors JavaScript’s ternary operator: T extends U ? X : Y.

A Basic Conditional Type

type IsString<T> = T extends string ? "yes" : "no";

type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"

A More Practical Example

Conditional types are most useful when combined with generics, letting a type adapt its shape based on what it’s given.

Flattening a Possibly-Array Type

type Flatten<T> = T extends (infer Item)[] ? Item : T;

type A = Flatten<string[]>; // string
type B = Flatten<number>;   // number (unchanged, since it isn't an array)

The infer Keyword

infer introduces a new type variable inside the extends clause, letting TypeScript extract and capture a piece of a type — like the element type of an array, or a function’s return type.

Extracting a Return Type with infer

type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never;

function greet() {
  return "hello";
}

type Result = MyReturnType<typeof greet>; // string

Distributive Conditional Types

When a conditional type is applied to a union, it automatically distributes over each member of the union individually, then combines the results back into a union.

Distribution Over a Union

type ToArray<T> = T extends any ? T[] : never;

type Result = ToArray<string | number>;
// Distributes to: string[] | number[] (not (string | number)[])

Chaining Conditional Types

Multiple conditional types can be chained together to express more complex, multi-branch logic entirely at the type level.

Chained Conditional Type

type TypeName<T> =
  T extends string ? "string" :
  T extends number ? "number" :
  T extends boolean ? "boolean" :
  "object";

type A = TypeName<42>;    // "number"
type B = TypeName<true>;  // "boolean"

This is Advanced, Library-Level TypeScript

Conditional types (especially combined with infer) are mostly seen in library and utility-type code, not everyday application code — but recognizing the pattern helps when reading type errors from libraries you depend on.

Best Practice

Reach for conditional types when building reusable, generic utilities. In application code, prefer simpler, explicit types wherever possible — conditional types can quickly become hard to read.

Interview Questions

Quick Quiz

1. What does T extends U ? X : Y mean?

2. What does the infer keyword do inside a conditional type?

3. What happens when a conditional type is applied to a union type?