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

TypeScript如何限定Map值类型同时保留原键类型?

解决方案

要同时满足「值类型必须为A」和「保留键的字面量类型」这两个需求,有两种实用的TypeScript实现方式:

方式一:使用satisfies关键字(TS 4.9+ 推荐)

satisfies是TypeScript 4.9新增的特性,它能检查对象是否符合指定类型,但不会覆盖TS对对象本身的类型推断——既会验证每个值都是A类型,又能保留as const带来的键字面量和只读特性。

type A = {
  name: string;
  description: string;
};

const MY_MAP = {
  unknown: {
    name: 'unknown',
    description: 'unknown',
  },
  error: {
    name: 'error',
    // 此处会触发TS错误:缺少必填属性"description"
  },
} as const satisfies Record<string, A>;

// MyMapKeys 类型为 'unknown' | 'error',符合预期
type MyMapKeys = keyof typeof MY_MAP;

方式二:泛型辅助函数(兼容低版本TS)

如果你的TS版本低于4.9,可以通过泛型函数实现约束。函数的泛型参数会强制输入对象的所有值为A类型,同时返回时用as const保留原对象的字面量类型:

type A = {
  name: string;
  description: string;
};

// 定义泛型辅助函数,约束输入对象的所有值都为A类型
const createTypedMap = <T extends Record<keyof T, A>>(map: T) => map as const;

// 传入对象时,TS会检查每个值是否符合A类型
const MY_MAP = createTypedMap({
  unknown: {
    name: 'unknown',
    description: 'unknown',
  },
  error: {
    name: 'error',
    // 此处会触发TS错误:缺少必填属性"description"
  },
});

// MyMapKeys 类型为 'unknown' | 'error'
type MyMapKeys = keyof typeof MY_MAP;

核心原理

这两种方式的核心都是分离「类型检查」和「类型推断」:

  • 不直接用Record<string, A>给变量赋值(否则键类型会被拓宽为string);
  • 而是通过satisfies或泛型约束做类型校验,同时保留原对象的字面量类型推断结果。

内容的提问来源于stack exchange,提问作者rollingcodes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 11:25:27