I'm trying to define a type as a second level key for a given object. So for example, for object:
const myObj = {
vegetabes: {
legumes: ['chickpea', 'garbanzo', 'lentil'],
tubers: ['potatoe', 'carrot']
},
meat: {
farm: ['cow', 'goat', 'lamb'],
wild: ['deer', 'bear']
}
}
and function
const findRecipe = (firstLevelKey: keyof typeof myObj, secondLevelKey: ?????) => {
const collection = myObj[firstLevelKey][secondLevelKey]
...
}
What type should I give secondLevelKey
so that it is restricted to the keys inside the selected firstLevelKey
? Ex: if I call findRecipe('vegetabes', ...)
the only valid values for the second argument would be legumes
and tubers
. If that's not possible, it could be enough to restrict to any of the second level keys legumes
, tubers
, farm
and wild
. But the ideal would be to restrict based on the 1st key.
If anyone knows how to get this to work on a generic function <T>(firstLevelKey: keyof T, secondLevelKey: ?????) => {...}
that would be nice too. But the important part would be what's described in the previous paragraph
CodePudding user response:
You probably would want to introduce a generic to ensure the keys are related correctly:
const findRecipe = <T extends keyof typeof myObj>(
firstLevelKey: T,
secondLevelKey: keyof typeof myObj[T]) => {
const collection = myObj[firstLevelKey][secondLevelKey]
}
The fully generic version would be this:
function genericAccess<T, K extends keyof T>(
instance: T,
firstLevelKey: K,
secondLevelKey: keyof T[K]
) {
const item = instance[firstLevelKey][secondLevelKey];
}