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

TypeScript:如何从值受限的常量中获取可用键?

如何同时实现TypeScript对象的键类型推断与值类型限制?

我编写了如下代码:

export const mapLayers: Record<string, SomeObject> = { layer_a: {}, layer_b: {} } as const;
export type LayerId = keyof typeof mapLayers;

预期LayerId的类型为layer_a | layer_b,但实际它始终是string。移除Record<string, SomeObject>后能正确推断键类型,但会失去对mapLayers值的类型限制。请问如何同时实现正确的键类型推断和值的限制?


方案1:使用satisfies关键字(TypeScript 4.9+)

这是最直观简洁的解法,satisfies关键字的作用就是验证对象是否符合指定类型,同时保留对象字面量的原始具体类型信息:

type SomeObject = {};

export const mapLayers = { layer_a: {}, layer_b: {} } as const satisfies Record<string, SomeObject>;
export type LayerId = keyof typeof mapLayers; // 类型为 "layer_a" | "layer_b"

这样既保证了mapLayers的每个值都符合SomeObject类型,又能让TypeScript精确推断出键名的联合类型。

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

如果你的TypeScript版本低于4.9,用泛型函数可以实现同样的效果:

type SomeObject = {};

const createMapLayers = <T extends Record<string, SomeObject>>(obj: T) => obj as const;

export const mapLayers = createMapLayers({ layer_a: {}, layer_b: {} });
export type LayerId = keyof typeof mapLayers; // 类型为 "layer_a" | "layer_b"

泛型函数会约束传入的对象必须符合Record<string, SomeObject>,同时通过as const固化对象的字面量类型,让TS能推断出具体的键名。

方案3:手动指定键类型(不推荐)

也可以手动定义键的联合类型,再传给Record,但这种方式需要重复编写键名,后续维护容易出错:

type SomeObject = {};
type LayerNames = "layer_a" | "layer_b";

export const mapLayers: Record<LayerNames, SomeObject> = { layer_a: {}, layer_b: {} } as const;
export type LayerId = keyof typeof mapLayers; // 类型为 "layer_a" | "layer_b"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:08:27