TypeScript’s standard library does have a signature for Array.prototype.filter()
which will narrow the type of the array, but it will only use that signature if the compiler recognizes the passed-in callback as a type guard function whose return type is a type predicate of the form paramName is SomeType
. And, unfortunately, the compiler is not currently able to infer that a callback (like Boolean
or x => !!x
) is a type guard; you have to annotate it as such.
(See microsoft/TypeScript#16069 for the feature request to use some sort of control flow analysis to interpret certain functions as type guards.)
Here’s one such annotated callback:
const truthyFilter = <T>(x: T | false | undefined | null | "" | 0): x is T => !!x;
or if you really want you can use Boolean
as the implementation with a type assertion like
const truthyFilter2 = Boolean as any as <T>(x: T | false | undefined | null | "" | 0) => x is T;
That is sort of a generic truthiness detector, although TypeScript doesn’t really have a good way to represent all possible falsy values in the type system (NaN
is unrepresentable for exaple). Anyway you can see it in action like this:
function fn(arr: Array<false | undefined | MyEvent>) {
const item = arr[0];
if (truthyFilter(item)) {
item.eventDesc; // okay, no error
}
And now if you use it with filter()
the compiler will narrow it as expected:
const myEvents = arr.filter(truthyFilter)
// const myEvents: MyEvent[]
Okay, hope that helps; good luck!