如何在TypeScript中编写类型安全的按对象属性排序泛型函数
泛型按对象属性排序函数的正确实现
你之前的泛型写法逻辑错误,string extends T完全不符合TypeScript的泛型约束规则。要实现类型精确化和属性合法性校验,需要结合keyof操作符与泛型约束,确保传入的属性是对象的合法字段,且属性值支持toLowerCase()方法。
最终实现代码
function sortByProperty<T, K extends keyof T>( objects: T[], property: K ): T[] { // 创建数组副本避免修改原数组(若业务允许修改原数组,可直接用objects.sort) return [...objects].sort((a, b) => { // 泛型约束已确保property是T的合法属性,断言为string是因为我们只传入字符串类型的属性 const valueA = (a[property] as string).toLowerCase(); const valueB = (b[property] as string).toLowerCase(); if (valueA < valueB) return -1; if (valueA > valueB) return 1; return 0; }); }
关键优化点说明
属性合法性校验
- 泛型
<T, K extends keyof T>:T定义数组元素的类型,K被约束为T的所有属性名,传入非法属性时TypeScript会直接报错,比如给User类型传入"invalidProp"会提示类型错误。 - 自动校验属性值类型:当传入属性对应的类型不是string时,TypeScript会因为
toLowerCase()的调用报错,比如传入age(number类型)时会提示错误。
- 泛型
保留原数组类型
函数返回类型为T[],调用后返回的数组会完整保留原对象的类型信息,能获得精准的类型提示。避免副作用
用[...objects]创建原数组的浅拷贝后再排序,防止原数组被意外修改。
调用示例
// 定义测试类型 interface Product { name: string; price: number; } const products: Product[] = [ { name: "Laptop", price: 999 }, { name: "mouse", price: 25 }, { name: "Keyboard", price: 50 }, ]; // 按name排序(合法,name是string类型) const sortedProducts = sortByProperty(products, "name"); // 错误示例:传入price会报错,因为price是number类型,无法调用toLowerCase // const sortedByPrice = sortByProperty(products, "price");
简化排序逻辑(可选)
可以用localeCompare简化字符串比较逻辑:
return [...objects].sort((a, b) => (a[property] as string).toLowerCase().localeCompare((b[property] as string).toLowerCase()) );
内容的提问来源于stack exchange,提问作者MrSolarius
相关产品推荐
相关产品推荐

