如何在TypeScript中为可索引类型的键创建字符串字面量类型?
解决TypeScript索引类型提取具体字符串键字面量的问题
为什么keyof typeof myRecords失效?
你的MyRecords是索引签名类型,当给myRecords显式标注MyRecords类型时,TypeScript会丢弃对象的具体键名信息,只保留索引签名的约束。此时typeof myRecords的类型就是MyRecords本身,keyof MyRecords的结果是string | number,自然无法得到你想要的'foo' | 'bar'字面量类型。
正确的实现方式
方法1:使用satisfies关键字(TypeScript 4.9+)
satisfies可以确保对象符合目标类型,但同时保留自身的字面量类型信息,完美适配你的需求:
export type MyRecords = { [name: string]: string | number }; // 用satisfies确保对象符合MyRecords,同时保留具体键的字面量类型 const myRecords = { foo: 'a', bar: 1, } satisfies MyRecords; type KeysOfMyRecords = keyof typeof myRecords; // 类型为 'foo' | 'bar' const key: KeysOfMyRecords = 'foo'; // 合法 const invalidKey: KeysOfMyRecords = 'invalid'; // 类型错误,符合预期
方法2:泛型约束兼容低版本TS
如果你的TypeScript版本低于4.9,可以用泛型函数来保留字面量类型,同时约束对象符合MyRecords:
export type MyRecords = { [name: string]: string | number }; // 泛型函数约束输入对象符合MyRecords,同时返回原字面量类型 const createRecords = <T extends MyRecords>(obj: T) => obj; const myRecords = createRecords({ foo: 'a', bar: 1, }); type KeysOfMyRecords = keyof typeof myRecords; // 类型为 'foo' | 'bar'
总结
核心问题在于显式标注索引类型会丢失具体键的类型信息,通过保留对象的原始字面量类型(同时确保符合索引类型约束),就能提取出你需要的字符串键字面量类型。
内容的提问来源于stack exchange,提问作者cyrus-d
相关产品推荐
相关产品推荐

