Skip to content
创建时间: 2020年12月6日

一、什么是「映射类型」?

一句话定义:

用一个已有类型的 key,批量生成一个新类型

核心语法:

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

📌 这里的 in 不是 JS 的 in,而是 类型层面的遍历 key

二、最基础示例(一定要会)

1️⃣ 手写 Readonly<T>

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

等价于 TS 内置的:

ts
Readonly<T>;

2️⃣ 手写 Partial<T>

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

3️⃣ 手写 Required<T>

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

📌 -? 表示 移除可选修饰符

三、映射类型中的「修饰符」

修饰符一览

修饰符含义
readonly只读
?可选
-readonly移除只读
-?移除可选

示例:去掉 readonly

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

四、映射 + 条件判断(进阶)

1️⃣ 根据 key 过滤字段(核心技巧)

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 在映射类型里可以改 key

2️⃣ key 重命名(Vue / React 源码常见)

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

结果:

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

五、in 的本质理解(非常重要)

ts
[K in keyof T]

等价于:

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

👉 TS 会对 联合类型自动展开

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

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

六、真实前端场景

1️⃣ 表单校验规则

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

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

2️⃣ Vue props 默认值

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

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

3️⃣ API 状态映射

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

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

七、常见误区(面试高频)

in 只能用在类型里

ts
[K in arr]; // ❌

忘记 keyof

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

以为 in 是运行时

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

八、映射类型 = TS 工具类型的底层

工具类型底层
Partialin + ?
Requiredin + -?
Readonlyin + readonly
Pickin + 条件
Recordin

九、记忆公式 🧠

  • keyof:拿 key
  • in:遍历 key
  • as:改 key
  • extends:筛 key