So basically I have data coming in from another via a post request in a large object. I need to pull out certain fields and put them in more specific objects with some of their fields remapped to then be inserted into a database.
I have this working in a non generic way, but I would like to have a more generic, but still completely type safe function.
This is a pared down version of the code as far as I have it right now.
import type { O } from 'ts-toolbelt';
const userFields = {
accountFirstName: 'firstName',
accountLastName: 'lastName',
email: 'email',
cellphone: 'cellPhone',
city: 'city',
state: 'state',
street: 'street',
zip: 'zip',
} as const;
const playerFields = {
playerId: 'sc_id',
playerFirstName: 'firstName',
playerLastName: 'lastName',
sizingJersey: 'jerseySize',
sizingShorts: 'shortSize',
} as const;
const allFields = {
...userFields,
...playerFields
}
type EventData = typeof allFields;
type InvertedRecord<R extends { [P in keyof R]: R[P]; }> = Record<keyof O.Invert<R>, string>;
type UserRecord = InvertedRecord<typeof userFields>
function objectKeys<Obj> (obj: Obj): (keyof Obj)[] {
return Object.keys(obj) as (keyof Obj)[];
};
// take just the user fields from the full data object and put them into a new object
const extractUser = (data: EventData) => {
const user: Partial<UserRecord> = {};
objectKeys(userFields).forEach((field) => {
user[allFields[field]] = data[field];
});
return user as UserRecord;
};
// A more generic extract function that takes the list of fields and the data object and extracts the fields into a new object
function genericExtract <T>(fields: T, data: EventData): T {
const obj: Partial<T> = {};
objectKeys(userFields).forEach((field) => {
obj[allFields[field]] = data[field]; // <--- obj's type doesn't get properly inferred so the assignment is not compatible
});
return obj as T;
}
TS Playground link for more context on the issue hat hand..