2

The following code in Typescript gives an assignment error on the last line

interface T {id: string}
let ts: Array<T> = []
let tMap: Map<string, T> =
    new Map (
        ts.map(t => [t.id, t])
    )

Similar code in a javascript environment works. Cant see what I am doing wrong

2 Answers 2

2

The problem is that the Map constructor wants an array of two-element tuples, but TypeScript does not infer tuple types from string literals. That means, the following:

const foo = [1, "two"]; 

is inferred as the array type Array<string | number> and not the tuple type [number, string]. If you want it to be [number, string] you can use an explicit type annotation like

const foo: [number, string] = [1, "two"];

or a type assertion like

const foo = [1, "two"] as [number, string];

Or, if you need this a lot, since it is possible to get TypeScript to infer a tuple type from function arguments, you can make a helper function like this:

const tuple = <T extends any[]>(...t: T) => t;

and then use it:

const foo = tuple(1, "two"); // inferred as type [number, string]

Any of those will help you get [t.id, t] to behave properly. Let's try the last one:

interface T { id: string }
let ts: Array<T> = []
let tMap: Map<string, T> =
  new Map(
    ts.map(t => tuple(t.id, t))  // okay 👍
  );

Hope that helps. Good luck!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your suggestion. I think I slightly prefer @ShamPooSham's work around.
0

Seems like Typescript can't infer the the map content as tuples, which should probably be reported as a bug. But I found a workaround which I think is acceptable, by explicitly writing the type of the map content:

let tMap: Map<string, T> =
  new Map(ts.map<[string, T]>(t => [t.id, t]))

1 Comment

Thank you. Clearly tuples are second class citizens compared to union types. As you suggest, there seems to be enough information to have inferred the tuple type, so I agree, it looks like a buglet. Your casting suggestion does the trick neatly.

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.