The object of settings like this:
const settings = {
groupOne: {
settingOne: 'string',
settingTo: 123,
},
groupTwo: {
settingThree: true,
},
};
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?
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.
typeof group
is just GroupKey
. So the function needs to know the type of the specific key, which means it needs to be generic.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]