#Filtering array with discriminated union?

21 messages · Page 1 of 1 (latest)

elfin ocean
#

Good afternoon,

I've created an object with a discriminated union and attempting to filter an array that contains these objects and subsequently map over these objects.

Unfortunately after I've filtered the array for the discriminating property, the map function is no longer aware that the discriminating property was filtered for and it complains that the additional property does not exist.

How might I inform the map that this property does exist?

Example below.

Thanks

brittle juncoBOT
#
smashman#0

Preview:```ts
type Item = {name: string} & (
| {hasGetter?: false}
| {hasGetter: true; getter: () => string}
)

const items: Item[] = [
{name: "one"},
{name: "two", hasGetter: true, getter: () => "cake"},
]

const itemsFromGetters = items
.filter(item => item.hasGe
...```

opaque lark
#

your filter callback needs to return a type predicate instead of a plain boolean

elfin ocean
#

How would I write a predicate for this example?

opaque lark
#

they can be inferred nowadays, but it's not in this case since your type isn't really a discriminated union (because the discriminant is optional in one of the variants)

#

if you're comfortable with in narrowing, you don't even need a DU:

brittle juncoBOT
elfin ocean
#

oh interesting

#

Ah well in my actual code it's not just a hasGetter

#

I guess I might stil be able to get rid of that property

opaque lark
#

if not it also works the way you want when you make the property required:

brittle juncoBOT
#
mkantor#0

Preview:```ts
type Item = {name: string} & (
| {hasGetter: false}
| {hasGetter: true; getter: () => string}
)

const items: Item[] = [
{name: "one", hasGetter: false},
{name: "two", hasGetter: true, getter: () => "cake"},
]

const itemsFromGetters
...```

opaque lark
#

and then yet another option is explicitly annotating the return type of that callback as a type predicate (the syntax for that is explained in the handbook link i shared above)

wary bramble
#

Doing item.hasGetter === true should fix the issue

#
const itemsFromGetters = items
  .filter((item) => item.hasGetter === true)
  .map((item) => ({ name: item.getter() })); // No error
opaque lark
#

oh nice, i didn't realize that would do the trick

elfin ocean
#

Ok, this isn't quite working on the original code as I am using Object.entries. Lemme whip up an example to share

#

I can make another question if you would prefer

opaque lark
#

FYI i'm heading out the door in a moment and probably won't be back on discord until tomorrow

#

yeah maybe a new thread would be best?

elfin ocean
#

Ok will do. Thanks