Filtering an Object in TypeScript

Steve Ruiz 2 min read

Filtering an Object in TypeScript

Ever need to filter properties from an object? Here’s how to do it.

In JavaScript:

function filterObject(obj, fn) {
  return Object.fromEntries(Object.entries(obj).filter(fn))
}

It’s a bit trickier in TypeScript:

type Entry<T> = {
  [K in keyof T]: [K, T[K]]
}[keyof T]

function filterObject<T extends object>(
  obj: T,
  fn: (entry: Entry<T>, i: number, arr: Entry<T>[]) => boolean
) {
  return Object.fromEntries(
    (Object.entries(obj) as Entry<T>[]).filter(fn)
  ) as Partial<T>
}

In either case, we can use our filterObject helper to return a new copy of an object with certain keys removed. Our filter function works just like Array.filter, except that its callback function’s first parameter will be the property’s key value pair as array ([key, value]).

const author = { name: "Steve", age: 93, height: 241 }

const onlySteves = filterObject(author, ([k, v]) => v === "Steve")
// { name: "Steve" }

const onlyNumbers = filterObject(author, ([k, v]) => typeof v === "number")
// { age: 93, height: 241 }

const onlyNames = filterObject(author, ([k, v]) => k === "name")
// { name: "Steve" }

Older Browsers

If you wanted to do this by hand (or perhaps in older browsers without polyfills for Object.fromEntries and Object.entries), you could also do it this way: create a shallow copy of the object, iterate once to generating the entries, and then iterate again to delete filtered properties.

function filterObject2<T extends object>(
  obj: T,
  fn: (entry: Entry<T>, i: number, arr: Entry<T>[]) => boolean
): Partial<T> {
  const next = { ...obj }

  const entries: Entry<T>[] = []

  for (const key in obj) {
    entries.push([key, obj[key]])
  }

  for (let i = 0; i < entries.length; i++) {
    const entry = entries[i]
    if (!fn(entry, i, entries)) {
      delete next[entry[0]]
    }
  }

  return next
}

Enjoy!