Is there a way of mapping the type of each field of an object to another type with TypeScript?
More specifically, I'm trying to build a function that takes in some sort of type definition, runs a different function depending on the type of each field, and puts the result back into an object under the same name:
// Input to function
registerData({
bodyText: 'string',
isAdmin: 'boolean',
postCount: 'number'
});
// The function returns this:
{
bodyText: 'Lorem ipsum dolor sit amet',
isAdmin: true,
postCount: 20
}
// So the desired type would be:
{
bodyText: string,
isAdmin: bool,
postCount: number
}
Is there any way to get the correct type for this return value?
I'm not tied to this specific input format, but it would be useful to have some method of differentiating data of the same type (e.g. being able to define a separate function for int and float that both end up as a number[]).
It would be useful to be able to have any arbitrary types as output fields, as I may need to pass out functions or arrays instead of just primitive values.
I've already tried some trickery with infer, but it combines all of the types of all fields:
type DataType = 'string' | 'number' | 'boolean';
type DataDefinition = { [name: string]: DataType }
type DataReturn<T> = T extends { [K in keyof T]: infer Item } ? { [K in keyof T]: DataReturnItem<Item> } : never;
type DataReturnItem<T> =
T extends 'string' ? string
: T extends 'number' ? number
: T extends 'boolean' ? boolean
: never;
const registerData = <T extends DataDefinition>(data: T) => {
// Generate data based on field types
return data as DataReturn<T>;
}
If I call registerData with the example mentioned above, the type it produces is:
{
bodyText: string | bool | number,
isAdmin: string | bool | number,
postCount: string | bool | number
}
This solution is also really awkward, as it requires me to tack on another case to the extends statements for DataReturnItem<T>, which is going to get ugly fairly quickly.
{ output: string, data: 'formatted-date' }, or{ output: number, data: 'integer' }to be able to pass the relevant types, so that I can specify different functions to run to produce the same types? For arbitrary output types I can probably make do with the same type transformation for all types (sostringbecomes() => string,numberbecomes() => numberand so on), if that makes it any easier.