TypeScript Conditional Types

TypeScript tutorial

🔀 TypeScript Conditional Types (Beginner → Advanced)

Conditional Types in TypeScript let you create types that depend on other types.
They are like if–else statements, but for types, and are heavily used in utility types, libraries, and advanced interviews.


1️⃣ What Are Conditional Types?

A conditional type chooses one type or another based on a condition.

Syntax ⭐

T extends U ? X : Y
  • If T is assignable to U → result is X

  • Otherwise → result is Y


2️⃣ Basic Conditional Type Example

type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false

✔ Simple
✔ Easy to understand
✔ Interview favorite


3️⃣ Conditional Types with Union Types ⭐

Conditional types are distributive over unions.

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

type A = ToArray<string | number>;
// string[] | number[]

📌 Applied individually to each union member


4️⃣ Turning Off Distribution ⚠️

Wrap type in a tuple to prevent distribution.

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

type A = ToArray<string | number>;
// (string | number)[]

✔ Important advanced concept


5️⃣ Conditional Types with infer ⭐⭐

infer lets TypeScript extract a type.

Example: Extract Return Type

type MyReturnType<T> =
T extends (...args: any[]) => infer R ? R : never;
type A = MyReturnType<() => number>; // number
type B = MyReturnType<(x: string) => boolean>; // boolean

✔ Core of many utility types


6️⃣ Extracting Array Element Type

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


7️⃣ Conditional Types with Objects ⭐

type HasId<T> = T extends { id: number } ? true : false;

type A = HasId<{ id: 1; name: string }>; // true
type B = HasId<{ name: string }>; // false

✔ Useful for API models


8️⃣ Filtering Types from Unions ⭐⭐

Remove null and undefined

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

📌 This is how built-in NonNullable<T> works


9️⃣ Built-in Utility Types Using Conditional Types ⭐⭐⭐

Many TypeScript utility types are based on conditional types.

Utility Type Purpose
Exclude<T, U> Remove types
Extract<T, U> Keep matching types
NonNullable<T> Remove null/undefined
ReturnType<T> Function return type
Parameters<T> Function parameters

Example

type A = Exclude<string | number, number>; // string
type B = Extract<string | number, number>; // number

🔟 Conditional Types with never 🔥

type IsNever<T> = T extends never ? true : false;

type A = IsNever<never>; // true
type B = IsNever<string>; // false

✔ Used in exhaustive checks


1️⃣1️⃣ Real-World Example ⭐⭐

API Response Wrapper

type ApiResponse<T> =
T extends Error
? { success: false; error: string }
: { success: true; data: T };
type A = ApiResponse<string>;
type B = ApiResponse<Error>;

✔ Clean
✔ Powerful
✔ Production-ready pattern


1️⃣2️⃣ Common Mistakes ❌

  • Forgetting distributive behavior

  • Overusing complex conditional logic

  • Confusing extends with inheritance

  • Not using infer when needed


📌 Interview Questions (Must Prepare)

  1. What is a conditional type?

  2. Explain T extends U ? X : Y

  3. What does distributive conditional type mean?

  4. What is infer?

  5. How is Exclude<T, U> implemented?

  6. How to prevent distributive behavior?


✅ Summary

✔ Conditional types enable type-level logic
✔ Syntax: T extends U ? X : Y
✔ Distributive over union types by default
infer extracts types dynamically
✔ Foundation of utility & advanced types
✔ Essential for TypeScript mastery & interviews

You may also like...