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

如何在为对象字面量加类型约束时仍推导其键类型?

解决方案

要同时实现对象结构约束和保留具体键的类型推断,可以用泛型工具函数或satisfies关键字来替代直接给对象加索引类型注解。直接使用{[key: string]: Fruit}会让TypeScript把对象类型拓宽为通用索引类型,丢失具体键的信息;而下面的方法能在约束结构的同时,保留原对象字面量的具体类型。

方法一:泛型工具函数(推荐,易复用)

定义一个泛型函数,约束传入的对象必须符合指定结构,同时返回原对象的具体类型:

type Fruit = {
    color: string;
    taste: string;
};

// 泛型函数约束对象结构,同时保留原类型
const createFruitData = <T extends Record<string, Fruit>>(data: T) => Object.freeze(data);

// 创建data时,既会检查每个值是否符合Fruit结构,又保留具体键的类型
const data = createFruitData({
    apple: { color: "red", taste: "sweet" },
    banana: { color: "yellow", taste: "sweet" },
    peach: { color: "orange", taste: "sweet" },
    grape: { color: "violet", taste: "sweet" },
});

type data_key = keyof typeof data;
// 现在得到的是:type data_key = "apple" | "banana" | "peach" | "grape"

原理

  • T extends Record<string, Fruit>确保传入的对象所有值都符合Fruit类型,编辑时少写color或taste会直接报错,提供字段完整性提示。
  • 函数返回T类型而非通用索引类型,所以typeof data会保留原对象的具体键和值类型,keyof typeof data自然能得到具体的键联合类型。

方法二:satisfies关键字(TypeScript 4.9+支持)

无需额外定义函数,用as const保留字面量类型,结合satisfies约束结构:

type Fruit = {
    color: string;
    taste: string;
};

const data = Object.freeze({
    apple: { color: "red", taste: "sweet" },
    banana: { color: "yellow", taste: "sweet" },
    peach: { color: "orange", taste: "sweet" },
    grape: { color: "violet", taste: "sweet" },
}) as const satisfies Record<string, Fruit>;

type data_key = keyof typeof data;
// 同样得到:type data_key = "apple" | "banana" | "peach" | "grape"

原理

  • as const让对象的键和值都保留字面量类型,避免TypeScript自动拓宽类型。
  • satisfies关键字用来验证对象结构是否符合Record<string, Fruit>,但不会改变对象本身的类型,因此keyof typeof data仍能获取具体的键联合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:21:10