I'm working with TypeScript conditional types and trying to define a function that behaves differently based on whether a multiple
flag is true
or false
. Here's a simplified version of what I'm doing:
type TypeValue<T, M> = M extends true ? T[] : T
type ArgsTest<T, M> = {
value: TypeValue<T, M>
multiple: M
}
const test = <T extends { id: number }, M extends boolean>({
value,
multiple,
}: ArgsTest<T, M>) => {
return multiple ? value.map((v) => v.id) : value.id
}
I'm getting a TypeScript error on value.map
, saying that value
might not be an array..
Is there a way to get TypeScript to narrow value
correctly based on the multiple
flag? Or do i have to use function overloads?
M extends true
doesn't distinguish between true
and false
. It distinguishes between true
(or never
) and every other type.
Problematically for you, boolean extends boolean
, but not boolean extends true
, so when M
is boolean
, the runtime value of multiple
can be true, but you have constrained value
to be a non-array type.
You can fix this by making ArgsTest
a union type directly:
type ArgsTest<T> = {
value: T
multiple: false
} | {
value: T[]
multiple: true
};
const test = <T extends { id: number }>({
value,
multiple,
}: ArgsTest<T>) => {
return multiple ? value.map((v) => v.id) : value.id
}