Some Noob Student
Some Noob Student

Reputation: 14584

How do you create the generic type in Map.entries()?

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

Answers (1)

Tobias S.
Tobias S.

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

Related Questions