I got multiple interfaces, say Int1, Int2 and so on
interface Int1 {}
interface Int2 {}
And I want to create a registry, structured as
const Registry = {
"Int1": {
"obj1": {} as Int1,
"obj2": {} as Int1,
},
"Int2": {
"obj1": {} as Int2,
},
}
AFAIK TypeScript requires the key type to be a literal. If I define my interface names as literals, how can I use these literals to reference the actual interface as type? Seems like I could do it with mapped types but I cannot figure it out myself.
Like
type RegistryType = {
[theKey in "Int1" | "Int2"]: {
[x: string]: <<force the interfaces Int1 or Int2 respecting theKey>>
}
}
TypeScript doesn't expose anything that relates string literal types to the names of interfaces. TypeScript's type system is structural and not nominal so there's not supposed to be any vital importance on type names in the first place. I could imagine a world in which there were an intrinsic TypeToString<T>
helper for display purposes (such a world existed in the unmerged pull request at microsoft/TypeScript#40468) but I doubt you'd want to rely on that since the choice of what string to output is an implementation detail of the compiler.
Instead, the closest you can get is to manually define a mapping from particular string literal types to the corresponding interface types. For example:
interface IntMap {
Int1: Int1;
Int2: Int2
}
Once you do that you can use a mapped type as planned:
type RegistryType = { [K in keyof IntMap]: { [k: string]: IntMap[K] } }
/* type RegistryType = {
Int1: { [k: string]: Int1; };
Int2: { [k: string]: Int2; };
} */
Note that you could decide to forgo defining the interfaces in the first place, since the names aren't helping you. You could put the definitions of the interfaces inline inside IntMap
:
interface IntMap {
Int1: { /* definition of Int1 */ };
Int2: { /* definition of Int2 */ }
}
Then your RegistryType
would be the same, and if you need to refer to your previously named interfaces you could use indexed access types like IntMap["Int1"]
instead of Int1
. Essentially
type Int1 = IntMap["Int1"];
type Int2 = IntMap["Int2"];