Reputation: 14584
let out = [...m.entries()]
.map(([k, v]) => [k, { foo: v }]) // <-- k has type of 1st param; v has type of 2nd param; perfect!
.reduce((map, [k, fooV]) => { // <-- k & fooV has union type
// Do stuff with it
return map
}, new Map())
When you iterate over a Map.entries()
value, you can setup the parameters [k,v]
to correspond to the 1st & 2nd parameters perfectly with their respective types.
However, when I try to do this myself, the types of [k,fooV]
becomes a union type. I would like k
& fooV
to also have the type of 1st & 2nd parameter respectively.
In my mapper, I want to create the same type as Map.entries()
so that the reducer's parameter can also destructure with the types intact.
From the docs, Map.entries(): IterableIterator<[K, V]>;
makes [K, V]
look like an array. But I tried that above and it doesn't work. What is [K, V]
's real type? How do you create an instance of it?
Upvotes: 0
Views: 66
Reputation: 23845
There is an easy fix to also have good type inference in the reduce
function. You can return the arrray with as const
appended to the end.
let out = [...m.entries()]
.map(([k, v]) => [k, { foo: v }] as const) // <-- as const here
.reduce((map, [k, fooV]) => { // <-- k & fooV have correct types now
// Do stuff with it
return map
}, new Map())
The initial problem is that types of array literals are often inferred with a wider type than what you might expect. By using as const
we can force TypeScript to narrow down the type to be a tuple instead of any array.
Upvotes: 1