#Why does flatMap complain about incompatible types when it shouldn’t?

30 messages · Page 1 of 1 (latest)

granite owlBOT
#
.selrond#0

Preview:```ts
type Address = {
streetAddress: string
city: string
}

type GroupedValue = {
asset: {id: string}
value: string | number | boolean
}

type Field = {
fieldId: string
value?: string | number | Address
groupedValues?: GroupedValue[]
}
...```

candid stratus
#

I don’t understand why TS seemingly mixes up different types…

hoary coral
#

groupedValues and value are mutually exclusive, but you didn't tell ts that

#

that doesn't immediately solve it but it's likely an issue

candid stratus
#

why should I tell it? I’m constructing different objects based on some conditions and returning them from the flatMap — I don’t really get why TS cares here at all

#

I didn’t define the output type either

hoary coral
#

ah wait misread the error

hoary coral
#

the current issue is it's probably inferring the first branch for the return type and then that doesn't match the second branch

granite owlBOT
#
that_guy977#0

Preview:ts ... const result = data.flatMap<{ fieldType: string value: string | number | boolean | Address }>(field => "groupedValues" in field ? field.groupedValues.map(gv => ({ fieldType: gv.asset.id, value: gv.value, // This is always primitive (string | number | boolean) })) : [ { fieldType: field.fieldId, value: field.value, // This could be an Address object }, ] )

hoary coral
candid stratus
#

hmm this feels wrong somehow

#

What if I need to rely on inference?

hoary coral
#

yeah im not sure what could be done to improve inference here tbh

#

seems like it's because they're separate arrays.. which does give me an idea, hold on

#

yeah, this works.

granite owlBOT
#
that_guy977#0

Preview:ts ... const result = data.flatMap(field => [ ...("groupedValues" in field ? field.groupedValues.map(gv => ({ fieldType: gv.asset.id, value: gv.value, // This is always primitive (string | number | boolean) })) : [ { fieldType: field.fieldId, value: field.value, // This could be an Address object }, ]), ])

hoary coral
#

this works with your original definition of Field, too

#

though you do end up with undefined in your result

#

either you'd need an extra check, since you didn't specify that one or the other is present, or you could specify that one or the other is present

candid stratus
#

yeah and the type definitions are not ideal — Field can have both value and groupedValue

hoary coral
#

also when testing, i found that .map(...).flat(1) does work for inference, but that is less clean and slightly less performant

candid stratus
#

Yeah, map works, I don’t even care about the slightly worse perf at this point 😄 Better to have correct types

#

Thanks for your time!

hoary coral
# granite owl

well, this does work, but it's slightly more clunky lol

candid stratus
#

whatever, much nicer with automatic inference

hoary coral
#

optionals+intersection = both, none, either one
union = both, either one
discriminated union = either one

candid stratus
#

all fields can have value, some can have groupedValues as well

neon raptor
#

Original message was deleted 😂