Apologies if this has been asked already, I wasn't quite sure how to search for it.
Given a pre-defined type that maps keys to a type of value, is it possible to create a typed Map where the second parameter to the generic is inferred from the value used for the first?
For instance, I can do this with an object:
interface EntitiesMap {
persons: Person
pets: Pet
}
type EntitiesObject = { [K in keyof EntitiesMap]?: Array<EntitiesMap[k]> }
const a: EntitiesObject {
persons: [person1, person2]
}
const b: EntitiesObject {
persons: [person1, person2],
pets: [pet1]
}
But I can't figure out how (or if it's possible) to do something similar with a Map:
// doesn't work
type EntitiesMap = Map<K in keyof EntitiesMap, Array<EntitiesMap[k]>>
Here's a more full example (and here it is in a TS playground)
interface Entity {
type: string
}
interface Person extends Entity {
phoneNumber: number
}
interface Pet extends Entity {
favoriteFood: string
}
interface EntitiesMap {
person: Person
pet: Pet
}
class Household {
inhabitantsObject: { [K in keyof EntitiesMap]?: EntitiesMap[K][] } = {}
/* Can I do this with a Map() ? */
inhabitantsMap: Map<keyof EntitiesMap, EntitiesMap[K]> = new Map()
// inhabitantsMap: Map<K extends keyof EntitiesMap, EntitiesMap[K]> = new Map()
// inhabitantsMap: Map<K in keyof EntitiesMap, EntitiesMap[K]> = new Map()
getInhabitantsFromObj<T extends keyof EntitiesMap>(type: T) {
return this.inhabitantsObject[type]
}
getInhabitantsFromMap<T extends keyof EntitiesMap>(type: T) {
return this.inhabitantsMap.get(type)
}
}
const house = new Household()
const peopleFromObj = house.getInhabitantsFromObj('person')
const petsFromObj = house.getInhabitantsFromObj('pet')
// these two values are 'any', but i'm guessing that is because
// inhabitantsMap does not have a valid type
const peopleFromMap = house.getInhabitantsFromMap('person')
const petsFromMap = house.getInhabitantsFromMap('pet')