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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:15:33