What I have?
The object of settings like this:
const settings = {
groupOne: {
settingOne: 'string',
settingTo: 123,
},
groupTwo: {
settingThree: true,
},
};
What I want?
Function (and its type) that gets a group key and a setting key as parameters and returns value of it.
type GetSettingFunction = (group: GroupKey, setting: SettingKey<typeof group>)
=> Setting<typeof group, typeof setting>;
const getSetting: GetSettingFunction = (group, setting) => {
// some code here
}
I have implemented some intermediate types and it seems working
type Settings = typeof settings;
type GroupKey = keyof Settings;
type Group<T extends GroupKey> = {
[K in GroupKey]: T extends K ? Settings[T] : never;
}[T];
type SettingsGroup<T extends GroupKey> = {
[K in GroupKey]: K extends T ? Group<T> : never;
}[T];
type SettingKey<T extends GroupKey> = {
[K in GroupKey]: K extends T ? keyof SettingsGroup<K>: never;
}[T];
But I can not understand how to implement final type Setting<GroupKey, SettingKey>
. Can you help me, please?
CodePudding user response:
I'm going to vastly simplify this for you. You have a lot of complicated utility types that aren't doing you any favors.
type GetSettingFunction = <
GroupKey extends keyof Settings,
SettingKey extends keyof Settings[GroupKey]
>(
group: GroupKey,
setting: SettingKey
) => Settings[GroupKey][SettingKey];
A few things here.
- The function needs to be generic. Otherwise
typeof group
is justGroupKey
. So the function needs to know the type of the specific key, which means it needs to be generic. - And the function needs to be generic over the setting key as well, since that's needed to derive the return type. And this will use the first generic type to figure out its constraint.
- You can just drill into a type like
Settings[GroupKey][SettingKey]
without a mapped or conditional type.
Now this works:
const getSetting: GetSettingFunction = (group, setting) => {
return settings[group][setting]
}
getSetting('groupOne', 'settingOne') // string
Or to put it another way, you can write your Setting
type like this:
type Setting<
GroupKey extends keyof Settings,
SettingKey extends keyof Settings[GroupKey]
> = Settings[GroupKey][SettingKey]