Answering this question the solution was to specify type arguments on the Map constructor, like this:
const conditions3: ReadonlyMap<string, any> = new Map<string, any>([
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^
[FirstName.Alex, 'foo'],
[Lastname.Smith, 'bar']
]);
Note that the OP wanted to give conditions3 the type ReadonlyMap<string, any>, not just a Map<string, any>; otherwise we could have just removed the type annotation from conditions3 entirely.
Unfortunately, that means repeating the type arguments on both ReadonlyMap and Map.
In the general case, is there a way to tell TypeScript to infer the type arguments for the variable/const's type (ReadonlyMap in this example) from the type arguments on the value being assigned (Map in this example)? I don't mean solutions to this specific case (I think I'd probably have a function, perhaps one that literally provided a read-only map, at least in development builds), but a general infer-from-the-target solution?
My various naive approaches don't work (the first two inspired by Java's <>):
const conditions3: ReadonlyMap<> = new Map<string, any>([
// ^^^^^^^^^^^^^−−−−− Generic type 'ReadonlyMap<K, V>' requires
// 2 type argument(s).(2314)
[FirstName.Alex, 'foo'],
[Lastname.Smith, 'bar']
]);
const conditions3: ReadonlyMap<string, any> = new Map<>([
// Same error with no matching overloads the OP had −^^
[FirstName.Alex, 'foo'],
[Lastname.Smith, 'bar']
]);
const conditions3: ReadonlyMap = new Map<string, any>([
// ^^^^^^^^^^^−−−−− Generic type 'ReadonlyMap<K, V>' requires
// 2 type argument(s).(2314)
[FirstName.Alex, 'foo'],
[Lastname.Smith, 'bar']
]);
Is the repetition avoidable in the general case?
Here's the setup code (so it's in the question, not just linked):
export enum FirstName {
Alex = 'alex',
Bob = 'bob'
}
export enum Lastname {
Smith = 'smith',
Abrams = 'abrams'
}