我的改变:
-
T 和 U 通用参数是多余的。只需要T。
注意:我最初只是替换了你所有的U
参考文献与keyof T
,但随后将其拉出sortArg
促进
#2.
-
use 模板文字类型 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#template-literal-typesTS 4.1 中引入
-
你忘了修剪-
startsWith('-') 情况下的前缀
-
在 Typescript 无法缩小类型的情况下使用类型断言
必须给出逻辑流程(TS 团队一直在改进
TS 编译器的流程分析,所以我敢打赌有一天这将是自动的)
-
API改进:重命名了函数并添加了方便的sort
函数在代码中可读性更好(请参阅示例用法
位于解决方案代码之后)。
type sortArg<T> = keyof T | `-${string & keyof T}`
/**
* Returns a comparator for objects of type T that can be used by sort
* functions, were T objects are compared by the specified T properties.
*
* @param sortBy - the names of the properties to sort by, in precedence order.
* Prefix any name with `-` to sort it in descending order.
*/
export function byPropertiesOf<T extends object> (sortBy: Array<sortArg<T>>) {
function compareByProperty (arg: sortArg<T>) {
let key: keyof T
let sortOrder = 1
if (typeof arg === 'string' && arg.startsWith('-')) {
sortOrder = -1
// Typescript is not yet smart enough to infer that substring is keyof T
key = arg.substr(1) as keyof T
} else {
// Likewise it is not yet smart enough to infer that arg here is keyof T
key = arg as keyof T
}
return function (a: T, b: T) {
const result = a[key] < b[key] ? -1 : a[key] > b[key] ? 1 : 0
return result * sortOrder
}
}
return function (obj1: T, obj2: T) {
let i = 0
let result = 0
const numberOfProperties = sortBy?.length
while (result === 0 && i < numberOfProperties) {
result = compareByProperty(sortBy[i])(obj1, obj2)
i++
}
return result
}
}
/**
* Sorts an array of T by the specified properties of T.
*
* @param arr - the array to be sorted, all of the same type T
* @param sortBy - the names of the properties to sort by, in precedence order.
* Prefix any name with `-` to sort it in descending order.
*/
export function sort<T extends object> (arr: T[], ...sortBy: Array<sortArg<T>>) {
arr.sort(byPropertiesOf<T>(sortBy))
}
用法示例:
interface User {
name: string
id: string
age?: number
}
const users: User[] = [
{name: 'Harriet Tubman', id: '01', age: 53},
{name: 'John Brown', id: '02', age: 31},
{name: 'John Brown', id: '03', age: 59},
{name: 'James Baldwin', id: '04', age: 42},
{name: 'Greta Thunberg', id: '05', age: 17}
]
// using Array.sort directly
users.sort(byPropertiesOf<User>(['name', '-age', 'id']))
// using the convenience function for much more readable code
sort(users, 'name', '-age', 'id')