如何使用const断言从任意层级嵌套对象提取字面量类型?
从任意层级嵌套对象提取各层级字面量类型(TypeScript)
背景
之前处理过深度为2的嵌套对象结构,通过手动映射提取了各层级的字面量类型:
const grandkids = { Karen: { Ava: ['Alice', 'Amelia'], Emma: ['Sarah'], }, Mary: { Sophia: ['Grace'], }, } as const;
对应的类型提取代码:
type Grandmother = keyof typeof grandkids; // Karen|Mary type Mother = { [K in Grandmother]: keyof typeof grandkids[K]; }[Grandmother]; // Ava|Emma|Sophia type Kid = { [K in Grandmother]: { [M in Mother]: typeof grandkids[K][M extends keyof typeof grandkids[K] ? M : never]; }; }[Grandmother][Mother][number]; // Alice|Amelia|Sarah|Grace
问题延伸
当结构深度增加到3层时,手动映射的方式会变得繁琐且无法通用:
const greatgrandkids = { Beth: { Karen: { Ava: ['Alice', 'Amelia'], Emma: ['Sarah'], }, Mary: { Sophia: ['Grace'], }, }, Ruth: { Ella: { Scarlett: ['Charlotte'], }, }, } as const;
我们需要一种通用方式,提取任意层级的字面量类型:
type GreatGrandmother = /* 需要实现 */; // Beth|Ruth type Grandmother = /* 需要实现 */; // Karen|Mary|Ella type Mother = /* 需要实现 */; type Kid = /* 需要实现 */;
通用解决方案
通过递归条件类型,可以实现任意层级的键提取和叶子元素类型提取:
1. 通用类型工具定义
// 提取对象的直接键类型 type Keys<T> = T extends object ? keyof T : never; // 递归提取指定层级的所有键(Depth从0开始计数,对应最外层) type NestedKeys<T, Depth extends number, CurrentDepth extends 0[] = []> = CurrentDepth['length'] extends Depth ? Keys<T> : T extends object ? NestedKeys<T[keyof T], Depth, [...CurrentDepth, 0]> : never; // 递归提取叶子节点的元素类型(支持数组或单个值叶子) type LeafElement<T> = T extends readonly (infer U)[] ? U : T extends object ? LeafElement<T[keyof T]> : T;
2. 实际使用示例
针对深度3的greatgrandkids对象:
// 第0层(最外层):曾祖母 type GreatGrandmother = NestedKeys<typeof greatgrandkids, 0>; // Beth|Ruth // 第1层:祖母 type Grandmother = NestedKeys<typeof greatgrandkids, 1>; // Karen|Mary|Ella // 第2层:母亲 type Mother = NestedKeys<typeof greatgrandkids, 2>; // Ava|Emma|Sophia|Scarlett // 叶子元素:孩子 type Kid = LeafElement<typeof greatgrandkids>; // Alice|Amelia|Sarah|Grace|Charlotte
针对深度2的grandkids对象:
// 第0层:祖母 type Grandmother = NestedKeys<typeof grandkids, 0>; // Karen|Mary // 第1层:母亲 type Mother = NestedKeys<typeof grandkids, 1>; // Ava|Emma|Sophia // 叶子元素:孩子 type Kid = LeafElement<typeof grandkids>; // Alice|Amelia|Sarah|Grace
关键说明
- 必须给嵌套对象添加
as const断言,确保TypeScript保留所有字面量类型,而非推断为string等宽泛类型。 NestedKeys<T, Depth>通过递归遍历对象层级,直到达到指定深度后返回该层的所有键。LeafElement<T>自动递归遍历到最底层,提取叶子节点的类型(支持数组或单个值场景)。
内容的提问来源于stack exchange,提问作者rodrigocfd
相关产品推荐
相关产品推荐

