Home > Enterprise >  TypeScript: Getting the type of the property at keyof T
TypeScript: Getting the type of the property at keyof T

Time:09-22

I'm having a bit of fun by playing with TypeScript and its typing system - it's nothing critical, but maybe some of you find this as interesting or fun as me.

Since I often find myself sorting arrays by properties of said objects, I thought to myself, "why not implement a sortBy function?".

Array.prototype.sortBy = function <T, P extends keyof T>(
  this: T[],
  compareFn: (a: unknown, b: unknown) => number,
  key: P
): T[] {
  return this.sort((a, b) => compareFn(a[key], b[key]));
};

Usage:

interface A {
  keyA: string;
  keyB: number;
}
const arr: A[] = [
  { keyA: "a", keyB: 42 },
  { keyA: "b", keyB: 1337 },
  { keyA: "c", keyB: -1 },
];
arr.sortBy((a: number, b: number) => b - a, "keyB");

The implementation works, and I think it's cool that this is even possible to have the list of keys as a type variable - as far as I know this behavior isn't possible in C# for example.

There's just one last thing I'd like to clean up - those being the unknown types for the comparator. The compiler can't catch any errors ahead of runtime here which can be dangerous. Is it possible to tell TS "the type that the property P in T has"?

I imagine something like K extends typeof P in T or K extends typeof T[P].

If this is possible, I would be able to even add sub-keys to the function declaration to search by properties deeper inside the object tree.

PS: I know this is a pretty contrived problem, and I don't think that K extends typeof T[P] would be useful for many situations at all. But playing with code and having a discussion about it is great fun and deepens the understanding for the language in question.

CodePudding user response:

All you should have to do is reference the key value: T[P] see:

Array.prototype.sortBy = function <T, P extends keyof T>(
  this: T[],
  compareFn: (a: T[P], b: T[P]) => number,
  key: P
): T[] {
  return this.sort((a, b) => compareFn(a[key], b[key]));
};

Playground

  • Related