Im new to typescript and am stumbling on this issue. I've searched around for a while but have not been able to find an answer.
What I want to do is define a properly typed sorting function which takes two arguments; an array of objects and a property of that object (as a string) on which to sort (using the JS myArray.sort() method).
Each object has a structure of InterfaceObject defined as
interface InterfaceObject {
prop1: string
prop2: number
prop3: SomeEnum
}
The sorting function:
function sortBy(array: InterfaceObject[], sortKey: keyof InterfaceObject) {
array.sort((a,b) => b[sortKey] - a[sortKey]
}
Although this works, TS is not happy because the .sort() method requires the types 'any', 'number' or 'bigint', and it cannot tell what type a property of InterfaceObject holds.
ideal situation:
sortBy(array, 'prop2') // okay: as its a number and key of InterfaceObject
sortBy(array, 'prop1') // error: as its not a number
sortBy(array, 'nonExistentProperty') // error: as its not a key of InterfaceObject
Im thinking using generics would help here, but I dont know to approach them. Any help would be appreciated.
CodePudding user response:
This can be solved with generics.
function sortBy<
T extends Record<K, number>,
K extends string
>(array: T[], sortKey: K) {
array.sort((a, b) => b[sortKey] - a[sortKey])
}
We can define two generic types T
and K
where T
is the type of the elements of the array we pass to the function. T
is constrained to have a property K
which is of type number
and K
is constrained to be of type string
.
CodePudding user response:
Instead of using an arithmetic operation simply compare the values and return -1, 0, or 1 instead.
function sortBy(array: InterfaceObject[], sortKey: keyof InterfaceObject) {
array.sort((a, b) => b[sortKey] < a[sortKey]
? -1
: b[sortKey] > a[sortKey]
? 1
: 0)
}