Can I use Typescript generics to filter keys from an object?

Viewed 249

I have a filter function with working logic, but I don't know how to write its types:

export function filter<T>(object: T, ...keys: Array<keyof T>): ??? {
  let index = -1;
  const length = keys.length;
  const result = { ...object };

  while (++index < length) {
    const key = keys[index];
    if (key in object) delete result[key];
  }
  return result;
}

filter({ a: 1, b: 2 }, 'b')  // { a: 1 }

Typescript still think 'b' property exists, so I'm looking for a way to specify that keys get removed from T.

I'm familiar with Omit (but generally pretty new to Typescript), and I think it could play a role in this, but I haven't come up with a way to make it and the Array meet...

Does someone see the path I'm looking for?

(btw the specific signature of filter isn't important, if you have an alternative implementation that's more conducive to type-safety I'm happy to hear it)

1 Answers

The solution is to extract keyof T into a generic. This should work:

export function filter<T, K extends keyof T>(object: T, ...keys: Array<K>): Omit<T, K> {
  let index = -1;
  const length = keys.length;
  const result = { ...object };

  while (++index < length) {
    const key = keys[index];
    if (key in object) delete result[key];
  }
  return result;
}
Related