2

I have the following map:

var myMap = new Map<string, [string, number]>()

The values of this map are always going to be a 2-item array, the first item being a string, and the second item being a number

myMap.set("foo", ["bar", 42])

This works as expected. Additionally, have an array with extra members does not work, also as expected

myMap.set("foo", ["bar", 42, 0]) // too many arguments

The problem I'm having is defining this outside of the set():

var value = ["bar", 42]
myMap.set("foo", value)

This causes the following error:

Argument of type '(string | number)[]' is not assignable to parameter of type '[string, number]'.
  Type '(string | number)[]' is missing the following properties from type '[string, number]': 0, 1

I can fix this by forcing the type:

var value = <[string, number]>["bar", 42]

But I hate doing this as it seems too verbose (I very well may have arrays that are defined as 10 or 15 members). Is there anything else I can do to resolve this issue?

2 Answers 2

1

If you are defining these tuples statically (e. g. by writing them by hand in source code) and you're able to define the values as readonly, then you can use the as const type assertion to ensure TypeScript infers the tuple type rather than the array type:

var myMap = new Map<string, readonly [string, number]>()
const value = ['hello', 123] as const;
myMap.set("foo", value); // Works as expected
Sign up to request clarification or add additional context in comments.

2 Comments

hrm, interesting. Good to know! Although I don't know yet if my usecase would allow for that - I'll be looking over a collection, and the tuple is actually going to be composed of items in that collection. But I'll definitely give it a shot :)
Just did a quick check, and so far this is exactly what I'm looking for. Recently release feature too, which might explain why i couldn't find a lot of resources for it. Thanks! For more information, I found this article helpful: blog.logrocket.com/…
1

With a little helper we can define a type alias for the value type of the map which can be used instead:

type MapValue<M extends Map<any, any>> = M extends Map<any, infer V> ? V : never;

var myMap = new Map<string, [string, number]>()
var value: MapValue<typeof myMap> = ["bar", 42] // value: [string, number]
myMap.set("foo", value)

Playground link

3 Comments

Isn't that quite similar to forcing the Type on value Like blitzmann suggested in the end of his question?
@Steven yes but they mention "I very well may have arrays that are defined as 10 or 15 members" so I understood the "too verbose" to refer writing the individual types of the tuple members.
Well, both are correct. This helps specifically the verbosity of having many members, however I'm still interested if there is a way to infer the value without having to declare it (I assume not). I think I could also define type val = [string, number] then var myMap = new Map<string, val>(); value = <val>["bar", 42] which also seems to work and also helps with the situations in which I might have many different members

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.