Today I learned that in TypeScript, passing a function whose return type is a type predicate to Array#filter can narrow down its return type!

I have an array where some elements may either be an object or null (Array<T | null>). Usually I do this:
array.filter(x => x)While null values are effectively removed in runtime, the type system still sees the type of the resulting array as Array<T | null>. I just learned that I can write it this way instead:
array.filter((x): x is T => !!x)…or if I don’t want to hardcode the type of the element:
array.filter((x): x is NonNullable<typeof x> => !!x)Now I get Array<T>.
Other techniques exist that doesn’t require type annotations, such as using flatMap instead.
array.flatMap(x => x ? [x] : [])Or using _.compact or its equivalent:
const compact = <T,>(array: readonly T[]) => array.filter((x): x is NonNullable<T> => !!x)
compact(array)Updates:
- Thu, 15 Oct 2020:
Exclude<T, null | undefined>can be rewritten asNonNullable<T>