前端进阶之旅前端进阶之旅
  • 基础篇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 K extends keyof T 属性访问 T K
TyTypeScript泛型设计

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

对象类型、这次选择的键和读取结果需要一起关联,才能避免把所有字段值混成一团。

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

一次属性读取包含三个关联

  1. 对象类型声明能够按照契约读取哪些成员
  2. 具体键型保留本次选择的是哪一个键或键联合
  3. 字段值型根据这个选择计算能够返回的值类型

可选字段的读取仍可能得到 undefined,合法键不代表这个字段在本次对象中一定有值。

核心回答

先记住这个答案

keyof T 得到 T 在类型层可使用的属性键集合,K extends keyof T 限制本次键参数只能从中选择。返回类型 T[K] 再把选中的键映射到对应字段值,使读取名称得到字符串、读取标识得到数字。如果参数只写成宽 keyof T,返回值可能成为多个字段类型的联合。keyof 不是运行时枚举函数,也不保证对象恰好拥有这些自有可枚举键;索引签名、可选字段以及数字和符号键都需要结合实际契约理解。

  • K 约束本次键选择,T 描述被读取的对象
  • T[K] 把选中的键与对应字段值连接起来
  • 类型中的键集合不等于 Object.keys 的实际结果

为什么还需要第二个类型参数

只让函数接收 object 和 string,编译器无法证明任意字符串都是这个对象的合法键。T 保留对象结构,K 再捕获本次传入的键,两个参数之间的约束让实现可以安全表达属性访问,并让返回值跟随具体选择。

示例从同一用户对象分别读取标识和名称,调用结果拥有各自的字段类型。拼错键名会被拒绝。若调用方本来持有两个键的联合,返回值也会对应这两个字段的联合,这是输入信息不确定性的正常反映,不能强行期待某一个固定字段类型。

根据选中键保留字段返回类型TypeScript
function read<T, K extends keyof T>(object: T, key: K): T[K] {
  return object[key];
}
const user = { id: 7, name: 'Lin' };
const id = read(user, 'id');
const name = read(user, 'name');
// @ts-expect-error nick 不在当前对象的键集合中
read(user, 'nick');
const optional: { label?: string } = {};
const label = read(optional, 'label');

id 被推断为数字,name 为字符串,可选 label 的读取结果保留 undefined。预期错误确认不存在的键会被检查,函数没有声称能够自动验证任意外部对象的真实结构。

键并不总是字符串字面量

对象键在类型中可能包括字符串、数字或 unique symbol。带字符串索引签名的对象,其 keyof 可能包含 string 与 number,因为 JavaScript 的数字属性访问也会对应字符串形式的键。泛型工具若只支持字符串,应把这一限制写清楚。

对联合对象使用 keyof 时,能够直接操作的键也要考虑所有可能成员的共同契约,不能简单理解为收集任意分支全部键。需要读取分支专有属性时,应先收窄对象或设计相应类型变换,而不是把任意字符串断言成 keyof。

为什么 Object.keys 不能随意断言

运行时对象可能通过结构兼容携带类型声明之外的字段,Object.keys 又只枚举自有可枚举字符串键,不包含符号键。这与 keyof 所描述的静态使用能力并不是同一个集合。全局把所有 Object.keys 返回值断言成 keyof 数组,会隐藏这种差异。

如果工具控制了对象创建和字段集合,可以在小范围内提供经过论证的键辅助函数;开放输入则应检查键或只读取明确白名单。静态合法键也不代表字段值已经符合外部协议,缺字段、错误类型与动态修改仍属于运行时边界的责任。

回答前,多想一步

容易答错的地方

keyof 会在浏览器中返回所有对象键
它是类型运算,编译后没有枚举行为;实际枚举需要运行时 API,而且自有、可枚举与符号键规则可能与静态集合不同。
键是合法的就能保证读取结果有值
可选字段可能被省略,索引签名与相关编译选项也会影响未命中读取;应保留返回类型中的空值可能并按业务处理。
试着用自己的话回答

面试官还会怎么问?

为什么传入联合键后返回值变成联合?

调用者没有确定具体选中哪一个字段,函数只能保留所有可能返回值;若后续需要专有操作,应进一步缩小键或结果的范围。

泛型读取函数会校验服务端字段吗?

不会,输入声明必须由其他边界保证;读取函数只在已有类型契约内维持对象、键与值之间的关系,不负责解析未知响应。

只想接受字符串键应该怎么表达?

可把 K 限制到 keyof T 与 string 的交叉集合,明确拒绝数字或符号键;同时确认这种限制符合工具真实支持的运行时访问方式。

从一道题,走向一组知识

把知识连起来

泛型设计

TypeScript 泛型怎样保留输入和返回值的类型关系,为什么 any 做不到?

属性读取也是把多处类型信息关联起来的泛型设计

类型运算

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

需要按整组键创建新类型时转向映射类型

参考资料

  • TypeScript:Using Type Parameters in Generic Constraints
  • TypeScript:Keyof Type Operator

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

本题目录
  1. 先记住这个答案
  2. 为什么还需要第二个类型参数
  3. 键并不总是字符串字面量
  4. 为什么 Object.keys 不能随意断言
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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