You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Object.keys不遵循字典键类型,TypeScript中如何实现预期行为?

关于Object.keys()在数字索引对象下的类型问题

为什么Object.keys()返回字符串数组?

JavaScript中对象的键本质上只能是字符串或Symbol类型——哪怕你用数字作为键赋值,JS引擎也会自动把它转成字符串存储。TypeScript的类型定义严格贴合JS的运行时行为,所以lib.es5.d.ts里Object.keys()的返回类型被定义为string[],而非泛型。

TS风格的解决方式

如果你确定对象的键确实都是数字类型,可以通过以下方式实现预期的类型提示:

  • 类型断言:直接将结果断言为数字数组,注意需要自己保证运行时的类型安全(比如对象没有被额外添加字符串键):
    const obj: { [key: number]: string } = { 1: "a", 2: "b" };
    const keys = Object.keys(obj) as unknown as number[];
    
  • 自定义工具函数:封装一个类型约束更严格的函数,利用keyof T来推导数字键类型:
    function getNumberKeys<T extends { [key: number]: unknown }>(obj: T): (keyof T)[] {
      return Object.keys(obj) as (keyof T)[];
    }
    
    // 使用示例
    const obj: { [key: number]: string } = { 1: "a", 2: "b" };
    const keys = getNumberKeys(obj); // keys类型为number[]
    

官方未将Object.keys()设为泛型的原因

TypeScript的核心原则是不违背JavaScript的运行时行为。如果把Object.keys()定义为泛型并返回keyof T类型,会存在类型安全隐患:比如你在TS里定义了数字索引对象,但运行时可能有人给对象添加了字符串键,此时泛型返回的类型就和实际运行结果不符,反而会误导开发者。官方选择保守的string[]作为返回类型,是为了让开发者明确知晓JS的实际行为。

新版本是否解决了该问题?

截至2024年,TypeScript官方仍未修改Object.keys()的返回类型定义。因为上述的类型安全矛盾是JS底层逻辑决定的,只要JS对象的键处理规则不变,TS就不会调整这个类型定义。

内容的提问来源于stack exchange,提问作者G. B. Wanscher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:40:01