Home > Blockchain >  Ensure a function parameter is a key of an interface AND that the interface entry type is a number
Ensure a function parameter is a key of an interface AND that the interface entry type is a number

Time:08-03

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.

Playground

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)
}
  • Related