Home > other >  TypeScript type for "Object with key called ..."
TypeScript type for "Object with key called ..."

Time:01-08

I want to make a function like

function sortByKey<T>(items: T[], key: string): T[] {
  return items.sort((a, b) => a[key] - b[key]);
}

I need T[key] to be a number, but I'm not sure how to express that.

If I knew the key ahead of time I could obviously just do {key: number} but that doesn't work here.

I tried something like sortByKey<K>(items: {[k: K]: number}[], key: K) but that gives the error "An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead." I looked into mapped types but they don't seem to do what I need. Is something like this possible in TypeScript?

CodePudding user response:

You probably want the function to be generic both in T, the type of the items elements, and in K, the type of key. You can constrain K to be keylike (K extends PropertyKey) and constrain T to be a type with a number value at key K (T extends Record<K, number> using the Record<K, V> utility type):

function sortByKey<K extends PropertyKey, T extends Record<K, number>>(
  items: T[], 
  key: K
): T[] {
  return items.sort((a, b) => a[key] - b[key]);
}

You can't write {[k: K]: number} because that's an index signature which can't be generic. But you can write {[P in K]: number} using a mapped type. Mapped types are similar to but distinct from index signatures; see this answer for more information. Anyway, Record<K, number> is an alias for {[P in K]: number}, so you were getting close.

Playground link to code

  •  Tags:  
  • Related