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

TypeScript约束泛型属性类型时出现索引报错的解决方案

TypeScript 限定泛型对象属性类型的实现方案

报错原因

你定义的KeysWithValsOfType工具类型筛选逻辑本身没有问题,但TypeScript泛型系统不会自动将K extends KeysWithValsOfType<T, string>的约束,反向推导为「K是T的合法索引键、且T[K]类型为string」的关联关系,因此在函数内部通过a[sortKey]访问属性时,编译器无法确认K可以合法索引T类型,才会抛出2536类型错误。

可直接运行的正确实现

两种写法都可以满足需求,核心是给泛型补全明确的索引关联约束:

写法1:简化泛型约束(推荐)

不需要额外定义工具类型,直接通过Record约束泛型关系,TS会自动推导合法的排序键范围:

interface Thing {
  id: string;
  price: number;
  test: number;
  other: { stuff: boolean };
}

const list = [
  {
    id: "1",
    price: 0,
    test: 2,
    other: { stuff: true },
  },
  {
    id: "12",
    price: 0,
    test: 2,
    other: { stuff: true },
  },
] as Array<Thing>;

/**
 * 对对象数组按指定字符串属性排序
 * 仅允许传入值为string类型的属性作为排序键
 */
function doSomeSortingThingWithStringProperties<T extends Record<K, string>, K extends PropertyKey>(
  list: T[],
  sortKey: K
) {
  // 字符串比较推荐用localeCompare,比直接用<更严谨,支持本地化排序规则
  list.sort((a, b) => a[sortKey].localeCompare(b[sortKey]));
}

doSomeSortingThingWithStringProperties(list, "id");      // 编译正常通过
doSomeSortingThingWithStringProperties(list, "other");   // 编译报错:类型"{ stuff: boolean; }"不满足约束"string"
doSomeSortingThingWithStringProperties(list, "price");   // 编译报错:类型"number"不满足约束"string"
console.log(list);

写法2:保留原有自定义工具类型

如果你需要复用KeysWithValsOfType的筛选逻辑,只需要在泛型约束中交叉keyof T,明确告知编译器K是T的合法键即可:

type KeysWithValsOfType<T, V> = keyof {
  [P in keyof T as T[P] extends V ? P : never]: P;
};

function doSomeSortingThingWithStringProperties<T, K extends keyof T & KeysWithValsOfType<T, string>>(
  list: T[],
  sortKey: K
) {
  list.sort((a, b) => a[sortKey].localeCompare(b[sortKey]));
}

校验效果

  • 传入值为string类型的属性(比如示例中的id)时,编译正常
  • 传入值为非string类型的属性(比如值为对象的other、值为数字的price/test)时,编译器会直接拦截报错,完全符合预期。

内容的提问来源于stack exchange,提问作者Stéphane Gerber

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:24:19