如何从TypeScript接口的嵌套indexes中提取键联合类型?
解决TypeScript提取嵌套indexes键生成联合类型的问题
问题根源
- 父接口索引签名覆盖字面量类型:原
DB接口中indexes定义为{[key: string]: any},会让TypeScript把子接口MyDB里的具体字面量键(如by-parent、by-title)拓宽为通用string类型,无法保留字面量信息。 - 未处理可选属性的undefined场景:
indexes是可选属性(带?),所以T[K]['indexes']可能为undefined,原类型仅判断了null,导致逻辑错误。 - 变量名拼写错误:代码中
getAllInicies应为getAllIndexes,这也是直接报错的原因之一。
修复方案
步骤1:重构DB接口
将DB中的indexes改为宽泛的object类型,避免索引签名覆盖子接口的具体结构:
interface DB { [key: string]: { indexes?: object | null; }; }
步骤2:修正getAllIndexes类型
使用NonNullable排除null和undefined,再通过类型推断提取具体索引键:
type getAllIndexes<T extends DB> = { [K in keyof T]: NonNullable<T[K]['indexes']> extends infer Indexes ? keyof Indexes : never; }[keyof T];
完整测试代码
interface DB { [key: string]: { indexes?: object | null; }; } interface MyDB extends DB { folders: { indexes: { 'by-parent': string; }; }; content: { indexes: { 'by-title': string; }; }; } type getAllIndexes<T extends DB> = { [K in keyof T]: NonNullable<T[K]['indexes']> extends infer Indexes ? keyof Indexes : never; }[keyof T]; // 类型为"by-parent" | "by-title",无报错 const index: getAllIndexes<MyDB> = 'by-parent'; const index2: getAllIndexes<MyDB> = 'by-title'; // 以下代码会报错,符合预期 // const index3: getAllIndexes<MyDB> = 'invalid';
原理说明
- 重构
DB接口后,MyDB中indexes的具体键类型会被TypeScript保留,不会被拓宽为通用string。 NonNullable<T[K]['indexes']>过滤掉null和undefined,确保后续处理的是有效索引对象。- 通过
infer Indexes推断每个表对应的索引对象类型,取keyof Indexes得到该表的索引键,最后通过[keyof T]将所有表的索引键合并为联合类型。
内容的提问来源于stack exchange,提问作者cani
相关产品推荐
相关产品推荐

