前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库TypeScript 映射类型 keyof in 索引签名
TyTypeScript类型运算

TypeScript 映射类型如何按键创建对象类型,和普通索引签名有什么区别?

映射类型让一组字段规则从已有键集合推导出来,减少手写结构与原模型不同步的问题。

前端进阶之旅 · 一题精讲更新于 2026.09.06
TypeScript#类型运算#类型系统
先看核心答案读代码示例
理解线索

一份字段规则作用于一组键

  1. 键的来源使用明确联合或从已有结构提取键
  2. 值的规则每个键对应固定类型或依赖 T[K] 的类型
  3. 字段修饰决定结果是否保留只读与可选能力

映射语法中的 in 是类型层枚举形式,与运行时检查属性存在的 in 操作符不是同一个过程。

核心回答

先记住这个答案

映射类型用类似 { [K in Keys]: ValueType } 的形式,为键集合中的每个键计算属性类型。Keys 可以是有限键联合,也常来自 keyof T;需要保留每个字段与原值的关系时,可以在结果位置使用 T[K]。普通字符串索引签名主要描述任意字符串键的值约束,而有限映射可以要求指定键都存在。同态形式还会保留原字段的只读与可选信息,除非显式调整修饰符。这些都是静态类型运算,不会自动遍历对象、创建字段或执行深层数据转换。

  • 映射从键集合逐项计算属性类型
  • 有限键映射可以要求指定字段齐全
  • 修饰符与运行时对象构造都需要明确处理

为什么有限映射比宽索引更具体

功能开关如果只允许搜索和导出两项,有限键联合可以让配置明确包含这两项。宽字符串索引允许任意键,却不一定要求这些指定键都出现。选择取决于协议是开放字典还是固定字段集合,不能只根据写法相似就互换。

示例先创建固定开关结构,再把用户字段映射为带 value 的包装对象。第二种形式保留了每个键对应的原字段类型,也延续只读和可选修饰。漏掉必需开关或写入只读字段会得到预期错误,说明映射结果仍是一份完整可检查的契约。

固定键映射与逐字段类型关联TypeScript
type Feature = 'search' | 'export';
type Flags = { [K in Feature]: boolean };
type Wrapped<T> = { [K in keyof T]: { value: T[K] } };
type User = { readonly id: number; nickname?: string };
const flags: Flags = { search: true, export: false };
// @ts-expect-error export 是必需开关
const missing: Flags = { search: true };
const wrapped: Wrapped<User> = { id: { value: 7 } };
// @ts-expect-error 同态映射保留 id 的只读修饰
wrapped.id = { value: 8 };

固定映射要求两个开关齐全,Wrapped 保留 id 的数字关系和只读属性,nickname 仍可省略。包装对象由实际字面量创建,类型映射本身不会把原 User 自动转换成这份值。

修饰符为何不是可忽略的小细节

映射可以显式增加或移除 readonly 和可选标记,常见工具会利用这些能力调整更新接口。但去掉可选标记只是改变静态要求,不会自动给缺失字段补默认值;把只读字段变可写也不会复制数据或解除运行时冻结。

如果映射仅处理对象的第一层,嵌套字段仍保持原来的结构与可变性。所谓深度只读或深度可选需要额外递归设计,还要决定函数、数组、日期和循环结构如何处理。不能因为用了映射语法就宣称得到完整深层转换。

把类型派生与值派生保持一致

运行时转换函数若承诺返回映射后的对象,仍必须实际遍历或构造全部必需字段,并处理原对象的键规则。Object.keys 不包含符号键,结构类型还可能允许额外字段,因此一个泛型循环是否真的对应完整映射,需要单独审查。

类型映射最适合减少明确结构间的重复声明,例如字段错误、包装值或固定权限表。应让键集合来自稳定事实来源,并在源模型变化时检查实现是否同步更新。编译器可以发现部分契约不匹配,却不会替转换函数生成缺失的业务逻辑。

回答前,多想一步

容易答错的地方

映射类型会自动生成对应的对象字段
它只产生静态结构,运行时对象仍由代码创建;若声明要求新增字段,实际构造逻辑也必须提供,不能只修改类型别名。
映射结果天然都是必需可写字段
同态形式会保留原有修饰,其他写法也可显式添加或移除;应查看 readonly 与可选标记,不要只关注字段值类型。
试着用自己的话回答

面试官还会怎么问?

键联合可以包含数字和符号吗?

合法属性键类型可以包含字符串、数字和符号,具体映射应符合这些规则;如果后续要拼接字符串键名,需要另外限制或转换键类型。

如何把可选字段改成必需字段?

可以使用移除可选标记的映射修饰符,但这只提高结果类型的要求;运行时必须确认字段已经存在,或提供真实默认值与校验。

映射能直接重命名每个属性吗?

可以通过 as 子句计算新键,或者用 never 过滤部分键;这属于键重映射,需要额外考虑同名冲突和字符串键处理规则。

从一道题,走向一组知识

把知识连起来

泛型设计

TypeScript 的 K extends keyof T 如何限制属性键,为什么返回类型要写 T[K]?

先理解键集合以及 T[K] 如何关联字段值

类型运算

TypeScript 映射类型的 as 怎样重命名和过滤键,重名之后会发生什么?

需要重命名和筛除字段时使用映射 as 子句

类型运算

TypeScript 同态映射为什么能保留数组和元组,加入 as 后还一样吗?

对数组和元组映射时检查结构保留的条件

参考资料

  • TypeScript:Mapped Types

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 为什么有限映射比宽索引更具体
  3. 修饰符为何不是可忽略的小细节
  4. 把类型派生与值派生保持一致
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑