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
相关产品推荐
相关产品推荐

