#Array filter method predicting wrong type

18 messages · Page 1 of 1 (latest)

polar hinge
#
const array: (string | undefined)[] = [];
const filtered = array.filter((v) => !!v);

filtered should have a type string[], but instead has the same type as array: (string | undefined)[]. Why is that?

clear bramble
#

it's because of how Array.filter works

#

you have an array of type string | undefined
and filter only removes some elements of the array
it doesn't change the type of the returned element
meaning the result will also be an array of string | undefined
just with less results

polar hinge
#

I see...

clear bramble
#

however, you can change the return type of the function used in the filter to fix that

polar hinge
#

Anyway I can case filtered to string[] by inferring array's type, without stating string[]?

ivory creek
#

it's not really inferring

#

!hb typeguards

#

!hb type predicate

brisk trenchBOT
clear bramble
#
const array: (string | undefined)[] = [];
const filtered = array.filter((v): v is string => !!v);
ivory creek
#

you can tell ts that the function has a specific meaning ^

clear bramble
#

!ts filtered

brisk trenchBOT
#
const filtered: string[] /* 2:7 */```
polar hinge
#

I know this, I meant to somehow use TS statements to infer the non-undefined type from array. In reality I have a type that is part of some namespace that I don't have access to because it's not exported, so I'd like to have the filtered array typed correctly without have access to the explicit type

ivory creek
#

ts doesn't do inferment across functions

#

you could extract that type by doing some type shenanigans ⬇️

brisk trenchBOT
#
type X = string;
declare const arr: (X | undefined)[];

type NewX = typeof arr extends Array<infer E> ? Exclude<E, undefined> : never
//   ^? - type NewX = string
const res = arr.filter((v): v is NewX => !!v);
//    ^? - const res: string[]