I have interface of values types:
interface ValuesTypes {
foo: string;
bar: number;
}
and Union of Controls:
type Controls = 'selectFoo' | 'tbxBar';
and map controls to values names:
const mapControlsToValues: Record<Controls, keyof ValuesTypes> = {
selectFoo: 'foo',
tbxBar: 'bar',
};
How can I get the ElementsTypes interface using code described above?
interface ElementsTypes {
selectFoo: string;
tbxBar: number;
}
CodePudding user response:
The way you defined mapControlsToValues
doesn't really work, because you are defining each value as a keyof ValuesTypes
, meaning, that each value can actually be foo
or bar
, and not the type that you passed in.
So, my advice is that you should rely on TypeScript's inference to do the job! In order to do that, you must create a generic function and use the "literal" type that you passed in. This way you will still have the same type safety, and be able to have concrete typing for your mapControlsToValues
object.
1- Create a generic function
function getControlValues<T extends Record<Controls, keyof ValuesTypes>>(arg: T){
return arg;
}
2- Extract the type of the generated type
const mapControlsToValues = getControlValues({
selectFoo: 'foo',
tbxBar: 'bar',
})
type ControlValuesType = typeof mapControlsToValues;
3- Create a new object type based on your ControlValuesType
type ElementsTypes = {
[Key in keyof ControlValuesType]: ValuesTypes[ControlValuesType[Key]];
};
And that's it, you have defined a type that follows the ElementsTypes interface. If you really need it to be an interface you can always extend the created type like so:
interface MyInterface extends ElementsTypes {}