TypeScript 索引签名:动态对象的类型安全

索引签名为键名未知的动态对象提供类型安全:{ [key: string]: number }。本文讲解语法、与已知属性混用、string vs number 键。

最佳实践
类型结构与组件组合插画

索引签名描述"任意键、统一值类型"的对象:interface Dict { [key: string]: number }。键名编译期未知但值类型受控——字典、缓存、动态配置的类型化方案。已知属性可与索引签名共存,但必须兼容其值类型。

动态属性问题

const scores = {};
scores['数学'] = 95;    // 普通类型推导对任意键无能为力

索引签名解法

interface ScoreMap {
  [subject: string]: number;
}

const scores: ScoreMap = {};
scores['数学'] = 95;        // ✓
scores['英语'] = '优秀';    // ✗ 编译错误:值必须是 number

键动态、值受控——字典结构的正确类型化。

与已知属性混用

interface Config {
  name: string;              // 已知属性
  [key: string]: string;     // 其他任意字符串键
}

约束:已知属性的类型必须兼容索引签名(name: string 兼容 [key: string]: string ✓;若索引签名是 number 则冲突)。

string vs number 键

JS 对象的键运行时都是字符串——number 索引签名([i: number]: T)专为类数组结构设计,访问时数字键自动转字符串仍类型安全。

Record:更常用的封装

type ScoreMap = Record<string, number>;          // 等价于索引签名
type RouteTable = Record<string, RouteConfig>;

语义相同、写法更短——日常用 Record,接口中混用时用索引签名。

常见问题(FAQ)

Q:索引签名和 Map 怎么选?

键是字符串且需要序列化(JSON)用对象+索引签名;键任意类型、需迭代顺序、频繁增删用 Map——Map 的类型是 Map<K, V> 天然精确。

Q:索引签名会让"不存在的键"不报错吗?

会——这正是它的语义(任意键合法)。拼写检查需求强的场景用精确接口而非索引签名。

Q:noUncheckedIndexedAccess 是什么?

严格选项:索引访问返回 T | undefined——逼你处理键不存在的情况。大型项目建议开启,配合可选链使用。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台