I would like to flatten down an object. This works well on the js side, but ts is a bit tricky to convert the object correctly.
I created a js method which converts a objects like this:
const from = {
red: '#red-val',
green: {
200: '#green-200-val',
300: '#green-300-val',
DEFAULT: '#green-default-val',
},
}
to this:
const to = {
red: '#red-val',
green: '#green-default-val',
'green-200': '#green-200-val',
'green-300': '#green-300-val',
}
On the js side, this works fine, but obviously Typescript doesn't understand this conversion, which is why I need to create a custom type for it.
So I created a couple of generic types, which are a bit hacky, but seems to work at first glance.
type HEX_VAL = `#${string}`;
type Props = {
[K in string]:
| HEX_VAL
| {
[IK in string]: HEX_VAL;
};
};
type ConvertChildKey<K extends string, P extends string> = K extends 'DEFAULT'
? P
: `${P}-${K}`;
type FlatColorKeys<P extends Props> = {
[K in keyof P]: P[K] extends Props
? //@ts-ignore
ConvertChildKey<keyof P[K], K extends string ? K : never>
: K;
}[keyof P];
type FlatColorsSettingsT<T extends Props> = Record<FlatColorKeys<T>, HEX_VAL>;
But here is the problem:
// this works fine. Hovering over this type, shows the correct result.
type ExampleConversion = FlatColorsSettingsT<{
red: '#red-val';
green: {
200: '#green-200-val';
300: '#green-300-val';
DEFAULT: '#default-color';
};
blue: {
300: '#sddsf';
};
}>;
// does not work fine. Hovering over this const just shows the generic type and not the result of it.
const ExampleMethodConversion = flatColorsSettings({
red: '#red-val',
green: {
200: '#green-200-val',
300: '#green-300-val',
},
});
Link to Playground. It includes also the js part.
Is there a better way to achieve the desired result? And to get the converted type and not the generic type when executing the method?
Thanks!