Home > Software engineering >  Passing an array through filter does not narrow element type
Passing an array through filter does not narrow element type

Time:12-19

I have an interface with two optional properties:

interface A {
  one?: string;
  two?: string;
}

Then I'd like to pass them inside of an array to a component that expects string[]

export const MyComponent: React.FunctionComponent<A> = ({one, two}) => {
  return <Query props={[one, two].filter(Boolean)} />
}

Even though I remove the undefined values with filter(Boolean), ts will still complain with the error:

Type '(string | undefined)[]' is not assignable to type 'string[]'.

Is this some kind of design issue and the only way is to do typecasting of

  return <Query props={[one, two].filter(Boolean) as string[]} />

?

CodePudding user response:

filter can narrow down the type of an array, but only if you pass it a type guard as the function. The Boolean constructor does not have the appropriate types.

For example, in the following code, the return type val is string means "this will return a boolean, and if it returns true, assume that val is a string":

[one, two].filter((val: string | undefined): val is string => Boolean(val));

If you're doing this a lot, you may want to make a reusable function:

const notUndefined = <T>(val: T | undefined): val is T => Boolean(val);
// used like:
[one, two].filter(notUndefined)
  • Related