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

如何移除TypeScript接口的字符串索引签名以正确使用keyof?

问题背景

现有接口定义如下:

interface RowItem {
  [prop: string]: unknown;
}

interface MyItem extends RowItem {
  id: number;
  name: string;
}

由于MyItem继承了带有字符串索引签名的RowItem,使用keyof MyItem会得到string | number | "id" | "name",无法直接限制函数参数为id/name这类明确声明的键名。因依赖库要求必须继承RowItem,且不想修改大量现有类型定义,需要一种方式提取出类型中不含索引签名的自有属性键。

解决方案

可以定义一个通用类型KnownKeys<T>,用于提取类型T中明确声明的属性键,排除字符串/数字索引签名:

type KnownKeys<T> = {
  [K in keyof T]: string extends K ? never : number extends K ? never : K
} extends { [_ in keyof T]: infer U } ? U extends keyof T ? U : never : never;

使用示例

获取MyItem的明确属性键:

type MyItemKnownKeys = KnownKeys<MyItem>; // 类型为 "id" | "name"

定义接收明确键名的函数:

function getItemProperty<T extends RowItem>(item: T, key: KnownKeys<T>) {
  return item[key];
}

const testItem: MyItem = { id: 123, name: "example" };
getItemProperty(testItem, "id"); // 类型正确,无报错
getItemProperty(testItem, "invalidKey"); // 类型检查报错,符合预期
类型原理说明

这个类型的核心逻辑是:

  1. 遍历T的所有键K,如果K是string的子类型(对应字符串索引签名)或number的子类型(对应数字索引签名),则将该键映射为never
  2. 通过条件类型的infer关键字,提取出所有非never的键,得到最终的明确属性键集合
对之前尝试的失败分析
  • Attempt1:由于unknown是所有类型的父类型,所有属性都会匹配MyItem[prop] extends unknown,导致结果全为never
  • Attempt2:Omit<MyItem, string>仅移除了字符串索引签名,但TS中对象的数字索引会被单独保留,因此剩余number类型的键,仍无法得到明确的属性名
  • Attempt3:Pick<MyItem, keyof MyItem>等价于原类型,没有过滤掉索引签名带来的string/number键

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:55:23