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

如何从TypeScript接口的嵌套indexes中提取键联合类型?

解决TypeScript提取嵌套indexes键生成联合类型的问题

问题根源

  1. 父接口索引签名覆盖字面量类型:原DB接口中indexes定义为{[key: string]: any},会让TypeScript把子接口MyDB里的具体字面量键(如by-parent、by-title)拓宽为通用string类型,无法保留字面量信息。
  2. 未处理可选属性的undefined场景:indexes是可选属性(带?),所以T[K]['indexes']可能为undefined,原类型仅判断了null,导致逻辑错误。
  3. 变量名拼写错误:代码中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:30:05