如何在TypeScript中定义只读Record的取值类型?
解决方案
首先,你当前给MyRecord标注的Readonly<Record<MyTypes, string>>会把值类型拓宽为通用的string,丢失了具体的字面量信息。要保留精确的取值类型,需要去掉这个显式类型标注,仅用as const让TypeScript推断出只读的字面量对象类型:
enum MyTypes { TypeA = 'TypeA', TypeB = 'TypeB' } // 去掉宽泛的类型标注,保留as const以获取精确字面量类型 const MyRecord = { [MyTypes.TypeA]: 'end-point-a', [MyTypes.TypeB]: 'end-point-b' } as const
接下来,提取MyRecord的取值类型,用typeof和索引类型实现:
// 提取MyRecord所有值的联合类型 type MyRecordValues = typeof MyRecord[keyof typeof MyRecord]; // 此时MyRecordValues的类型是 'end-point-a' | 'end-point-b'
然后定义getEndpoint函数,返回这个类型:
function getEndpoint(): MyRecordValues { // 示例逻辑,返回其中一个值 return Math.random() > 0.5 ? MyRecord[MyTypes.TypeA] : MyRecord[MyTypes.TypeB]; }
最后,你的switch语句就能正常工作,default分支的myEndpoint会被推断为never类型(因为所有可能的取值都被case覆盖了):
const myEndpoint = getEndpoint(); switch(myEndpoint){ case MyRecord[MyTypes.TypeA]: // 处理TypeA逻辑 break; case MyRecord[MyTypes.TypeB]: // 处理TypeB逻辑 break; default: // 这里myEndpoint类型为never,不会触发报错 const _exhaustiveCheck: never = myEndpoint; throw new Error(`Unexpected endpoint: ${_exhaustiveCheck}`); }
如果一定要给MyRecord加上Readonly<Record<MyTypes, ...>>的类型约束,可以用类型断言结合satisfies关键字(TypeScript 4.9+支持),既保留类型检查又不丢失字面量信息:
const MyRecord = { [MyTypes.TypeA]: 'end-point-a', [MyTypes.TypeB]: 'end-point-b' } as const satisfies Readonly<Record<MyTypes, string>>;
这样既确保MyRecord符合Readonly<Record<MyTypes, string>>的结构,又能让TypeScript推断出具体的字符串字面量值类型。
内容的提问来源于stack exchange,提问作者distante
相关产品推荐
相关产品推荐

