This is a long shot but I would like to be able to generate a new interface from an existing one but with key names that are derived for the originals.
Below is an example of the kind of thing I would like to be able to do:
Given this source object:
interface Car {
brand: Brand;
model: string;
year: number;
}
I would like to be able to declare an interface:
interface CarSetters {
setBrand: (brand: Brand) => any;
setModel: (model: string) => any;
setYear: (year: number) => any;
}
but I don't want to have to declare it manually like above. Rather, I would like to be able to use it like:
type CarSetters = Setters<Car>
or
type CarState = Car & Setters<Car>
It looks to be a pretty simple mapping:
type Brand = boolean;
interface Car {
brand: Brand;
model: string;
year: number;
};
type CarSetters = {
[T in keyof Car as `set${Capitalize<T>}`]: (newValue: Car[T]) => any;
};
To keep symbols from causing issues, you can do:
type CarSetters = {
[T in keyof Car as T extends symbol ? never : `set${Capitalize<T>}`]: (newValue: Car[T]) => any;
};
or
type CarSetters = {
[T in keyof Car as T extends symbol ? never : `set${Capitalize<T>}`]: (newValue: Car[T]) => any;
} & {
[T in keyof Car as T extends symbol ? T : never]: Car[T];
};