Skip to content
Created: December 6, 2020

1. What is "mapping type"? ​

One sentence definition:

Use an existing type key to batch generate a new type

Core syntax:

ts
type NewType<T> = {
  [K in keyof T]: T[K];
};

📌 The in here is not the in of JS, but the type-level traversal key

2. The most basic example (must know) ​

1️⃣ Handwritten Readonly<T> ​

ts
type MyReadonly<T> = {
  readonly [K in keyof T]: T[K];
};

Equivalent to TS built-in:

ts
Readonly<T>;

2️⃣ Handwritten Partial<T> ​

ts
type MyPartial<T> = {
  [K in keyof T]?: T[K];
};

3️⃣ Handwritten Required<T> ​

ts
type MyRequired<T> = {
  [K in keyof T]-?: T[K];
};

📌 -? means remove optional modifiers

3. "Modifiers" in mapping types ​

List of modifiers ​

ModifierMeaning
readonlyRead only
?Optional
-readonlyRemove read-only
-?Remove optional

Example: remove readonly ​

ts
type Mutable<T> = {
  -readonly [K in keyof T]: T[K];
};

4. Mapping + conditional judgment (advanced) ​

1️⃣ Filter fields based on key (core skills) ​

ts
type FilterString<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K];
};
ts
type User = {
  id: number;
  name: string;
  age: number;
};

type StringProps = FilterString<User>;
// { name: string }

📌 as can change the key in the mapping type

2️⃣ key renaming (common in Vue/React source code) ​

ts
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
ts
type State = {
  count: number;
  name: string;
};

Result:

ts
{
  getCount: () => number;
  getName: () => string;
}

5. Essential understanding of in (very important) ​

ts
[K in keyof T]

Equivalent to:

ts
K = "a" | "b" | "c";

👉 TS will automatically expand union types

ts
type Keys = "a" | "b";

type Obj = {
  [K in Keys]: number;
};
// { a: number; b: number }

6. Real front-end scenario ​

1️⃣ Form validation rules ​

ts
type Form = {
  username: string;
  password: string;
};

type Rules<T> = {
  [K in keyof T]: {
    required?: boolean;
    message?: string;
  };
};

2️⃣ Vue props default value ​

ts
type Props = {
  size: string;
  disabled: boolean;
};

type DefaultProps = {
  [K in keyof Props]?: Props[K];
};

3️⃣ API status mapping ​

ts
type Api = {
  getUser: () => void;
  getList: () => void;
};

type LoadingState<T> = {
  [K in keyof T]: boolean;
};

7. Common Misunderstandings (High Frequency Interviews) ​

❌ in can only be used in types

ts
[K in arr]; // ❌

❌ Forgot keyof

ts
[K in T] // ❌
[K in keyof T] // ✅

❌ Think in is runtime

ts
// 映射类型不会生成 JS 代码

8. Mapping type = bottom layer of TS tool type ​

Tool TypeBottom
Partialin + ?
Requiredin + -?
Readonlyin + readonly
Pickin + condition
Recordin

9. Memory formula 🧠 ​

  • keyof: get key
  • in: traverse key
  • as: change key
  • extends: sieve key