Skip to content
Created: December 7, 2020

1. Usage 1: Generic constraints (Constraint) ​

  • Limit the "value range" of generics

1️⃣ The most basic example ​

ts
function getLength<T extends { length: number }>(value: T) {
  return value.length;
}
  • ✅ string / array
  • ❌ number

📌 extends = T must satisfy a certain structure

2️⃣ Constraint key (UHF) ​

ts
function getValue<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

Here:

  • K can only be the key of T
  • Otherwise, an error will be reported directly

3️⃣ Constraint function type ​

ts
type Fn<T extends (...args: any[]) => any> = T;

Common writing methods for React/Vue hooks types.

2. Usage 2: Conditional Types ​

  • Return different types like ternary expressions

1️⃣ Basic grammar ​

ts
T extends U ? X : Y

2️⃣ Basic example ​

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

type A = IsString<"a">; // true
type B = IsString<123>; // false

3️⃣ Common built-in tool types ​

Exclude ​

ts
type MyExclude<T, U> = T extends U ? never : T;

Extract ​

ts
type MyExtract<T, U> = T extends U ? T : never;

4️⃣ Determine function return value (actual combat) ​

ts
type Return<T> = T extends (...args: any[]) => infer R ? R : never;

(This is how ReturnType works)

3. Usage 3: Distribution condition type (Distributive) ​

  • Condition type + union type = automatic split calculation

📌 This is the most confusing part

1️⃣Look at an example ​

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

type A = ToArray<string | number>;

Calculation process:

ts
ToArray<string> | ToArray<number>;
// string[] | number[]

2️⃣ Conditions for distribution to occur (remember this) ​

  • Only dispatched if T is a "naked type parameter"

✅ Distribution:

ts
T extends U ? X : Y

❌ Not distributed:

ts
[T] extends [U] ? X : Y

3️⃣ Turn off distribution (very important) ​

ts
type NoDistribute<T> = [T] extends [string] ? true : false;

type A = NoDistribute<string | number>;
// false

4. Comparative summary of three usages ​

UsageWritingOccurrence time
Constraints<T extends U>Generic declaration
ConditionT extends U ? X : YType calculation
DistributionCondition + UnionAutomatic

5. How to use extends for real tool types? ​

1️⃣ NonNullable<T> ​

ts
type NonNullable<T> = T extends null | undefined ? never : T;

2️⃣ Parameters<T> ​

ts
type Params<T> = T extends (...args: infer P) => any ? P : never;

3️⃣ Awaited<T> ​

ts
type Awaited<T> = T extends Promise<infer R> ? Awaited<R> : T;

6. Front-end real scene ​

1️⃣ Determination of form value type ​

ts
type FieldValue<T> = T extends HTMLInputElement
  ? string
  : T extends HTMLSelectElement
    ? string
    : never;

2️⃣ API status type ​

ts
type ApiResult<T> = T extends null
  ? { success: false }
  : { success: true; data: T };

7. 3 combos of must-ask questions in the interview (standard answers) ​

Q1: How many uses of extends in TS? ​

  • 3 types: generic constraints/condition types/distribution condition types

Q2: When will distribution occur? ​

  • When the left side of extends is a naked type parameter and it is a union type

Q3: How to turn off distribution? ​

  • Wrap a layer with tuple [T] extends [U]

8. The ultimate memory formula 🧠 ​

  • declaration-time constraint → constraint
  • Judgment during calculation → condition
  • United Demolition → Distribution