Search code examples
typescripttypescript-generics

Generic type ascertaining a key is present in the type


Given this minimal example

interface Sorting {
  myValue: number
}

const mySort = (data: Sorting[]) => {
  data.sort((a: Sorting, b: Sorting) => {
    return a.myValue - b.myValue
  })
  return data
}

I would like to create some code that abstracts the myValue property, such that I could type safely write something as below

interface Sorting {
  [key]: number
}

const mySort = (data: Sorting[], [key]: "myValue") => {
  data.sort((a: Sorting, b: Sorting) => {
    return a[key] - b[key]
  })
  return data
}

Solution

  • You can make your sort function generic, and express the relation between the object type and the sort key in the generic type parameters:

    const mySort = <
      T extends { [k in K]: number },
      K extends keyof T
    >(data: T[], key: K) => {
      data.sort((a: T, b: T) => {
        return a[key] - b[key];
      })
      return data;
    };
    
    const data = mySort([{ myValue: 2 }, { myValue: 1 }], 'myValue');
    console.log(data);
    

    Playground link

    Now you can pass an array of any type to the sort function, as long as the key you're specifying corresponds to a numeric property of that type.