TypeScript泛型报错TS2345:对象数组通用排序函数类型不兼容
解决TS2345:类型'string | number | symbol'无法赋值给类型'never'的排序函数泛型问题
问题根源
你的createSortComparator函数返回的比较器类型定义过窄:它要求输入参数是仅包含目标键的对象{ [key in Key]: T[Key] },但数组sort方法需要的比较器是接受完整T类型对象的函数。这种类型不匹配导致泛型宽泛时,TypeScript无法正确推断类型,触发TS2345错误。
解决方案
修改createSortComparator的返回类型,让比较器接受完整的T类型对象(而非仅包含目标键的部分对象),同时调整内部比较逻辑的泛型约束,确保类型推断正确。
修改后的完整代码
// sort.ts export type SortOrder = "asc" | "desc"; // 调整泛型约束,明确Key是T的键类型 const descendingComparator = <T, Key extends keyof T>(a: T, b: T, sortBy: Key) => { const valA = a[sortBy]; const valB = b[sortBy]; // 基础类型比较逻辑,可扩展支持Date等其他可比较类型 if (valB < valA) { return -1; } if (valB > valA) { return 1; } return 0; }; // 调整返回类型为接受完整T对象的比较器 export const createSortComparator = <T extends object, Key extends keyof T>( sortOrder: SortOrder, sortBy: Key ): ((a: T, b: T) => number) => sortOrder === "desc" ? (a, b) => descendingComparator(a, b, sortBy) : (a, b) => -descendingComparator(a, b, sortBy);
验证使用示例
修改后,你的通用排序函数sortStuff可以正常工作,无需指定具体类型:
enum DummyKeys { supplierName = "supplierName", supplierId = "supplierId" } type Dummy = { [DummyKeys.supplierName]: string; [DummyKeys.supplierId]: number; }; const dummy: Dummy[] = [ { [DummyKeys.supplierName]: "test", [DummyKeys.supplierId]: 123 }, { [DummyKeys.supplierName]: "apple", [DummyKeys.supplierId]: 456 } ]; // 单个排序示例正常运行 const sortedDummy = dummy.sort( createSortComparator("asc", DummyKeys.supplierName) ); // 通用排序函数无类型错误 const sortStuff = <T extends object, Key extends keyof T>( objToSort: T[], keyToSort: Key ) => { objToSort.sort(createSortComparator("asc", keyToSort)); }; sortStuff(dummy, DummyKeys.supplierName); sortStuff(dummy, DummyKeys.supplierId); // 数字类型键也能正常排序
额外说明
如果需要支持非string/number的可比较类型(如Date),只需在descendingComparator中添加对应的类型判断逻辑即可,核心的泛型约束无需改动。
内容的提问来源于stack exchange,提问作者Daniel P
相关产品推荐
相关产品推荐

