I have the following type:
type mapOptions = {
'a': {},
'b': {
'somethingElse': string,
'somethingDiff': number
},
'c': {
'somethingC': string
}
}
Now I would like to create a Map, that can have it's keys set to the keys of my object, and take up for the value a specific object, one like this:
type innerMapObject<T extends keyof mapOptions> {
status: boolean,
options: mapOptions[T]
}
Basically, what I want, is that after I have my map, when fetching or setting values in it, to get the correct underlying option types:
const MyMap: Map<...> = new Map();
MyMap.set('d', {}); // error here, "d" is not a property of "mapOptions";
MyMap.set('a', {}); // works correctly
MyMap.set('c', {
"somethingD": "test"
}); // error here, the value object does not match "mapOptions["c"]"
/** This should be of type:
*
* {
* status: boolean,
* options: {
* somethingElse: string,
* somethingDiff: number
* }
* }
*
*
*/
const myBValue = MyMap.get("b");
Is it possible to somehow back-reference the key of the map inside the value associated with that key?
CodePudding user response:
Yes, although the code may look a little weird. Basically, the Map
type takes in two generics: K
for the key type and V
for the value type. This is similar to Record<K, V>
. However, due to the layout, there is no way to say that certain props from an object would have certain values because all of the keys have the same value type.
There is a workaround, though, because you can create an intersection of the Map
s to make TypeScript infer the overload signatures to allow specific keys to have specific values.
type MyMap = Map<"planet", { name: string; size: number }> & Map<"person", { name: string; age: number }>;
const myMap: MyMap = new Map();
// these work