映射类型通过 in 遍历 keyof 产生的联合类型,每次将键名变量(如 k)绑定为单个字面量类型,并在值位置用 t[k] 索引访问或结合条件类型、as 重命名实现键值动态转换与筛选。

映射类型通过 in 操作符遍历联合类型中的每个键,动态生成新类型,本质是“对键做运算,再重映射值”。关键不在 in 本身,而在于它左侧的键名变量(如 K in keyof T)如何参与类型推导和转换。
用 in 遍历 keyof 联合类型
in 只能作用于**联合类型**(包括 keyof 的结果),每次迭代取其中一个字面量类型作为键名。例如:
-
keyof { a: number; b: string }得到"a" | "b"—— 这是一个联合类型 -
K in keyof T表示:对联合中的每个成员(如"a"、"b")分别执行一次映射 - 左侧的
K是一个类型变量,在每次迭代中绑定为具体字符串字面量类型(不是值!)
在值类型位置使用 K 做索引访问
映射类型的右侧(冒号后)可利用 K 对原类型做索引访问,从而批量提取/转换属性类型:
-
[K in keyof T]: T[K]→ 等价于原类型(恒等映射) -
[K in keyof T]: T[K] | null→ 所有属性变为可空 -
[K in keyof T as `on${Capitalize<k>}`]: (e: any) => void</k>→ 键名变换 + 类型替换(TS 4.1+ 支持as重命名)
结合条件类型实现按需加工
在值类型中嵌套条件类型,可对不同属性做差异化处理:
-
[K in keyof T]: T[K] extends string ? number : T[K]→ 把所有字符串属性转成number -
[K in keyof T as T[K] extends Function ? never : K]: T[K]→ 排除函数属性(never使该键被剔除) - 注意:
as后的类型必须是字符串字面量或联合,否则会被忽略
实际应用:封装常用映射工具类型
比如实现 PartialByKeys<t k></t>,只让指定键变为可选:
type PartialByKeys<t k extends keyof t> = { [P in keyof T]: P extends K ? T[P]? : T[P] };</t>- 调用
PartialByKeys<user></user>→ 仅email和phone变可选 - 核心仍是
P in keyof T遍历所有键,再用P extends K判断是否属于目标键集合











