Last active
August 9, 2022 21:09
-
-
Save sunnyy02/7b0a768380057f2ed7541aba4d9f8d22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Firstly define the entities | |
type DataSchema = { | |
client: { | |
dto: { id: string, name: string}, | |
entity: {clientId: string, clientName: string} | |
}, | |
order: { | |
dto: { id: string, amount: number}, | |
entity: {orderId: string, quantity: number} | |
}, | |
} | |
// transvers to lookup the property type | |
type PropertyType<T, Path extends string> = Path extends keyof T ? T[Path] : never; | |
type lookup<T, Key extends keyof T, prop extends string> = PropertyType<T[Key], prop>; | |
// one liner version | |
type lookup2<T, Key extends keyof T, prop extends string> = prop extends keyof T[Key] ? T[Key][prop] : never; | |
// mapTo and MapFrom | |
type MapTo<T extends string> = `to${Capitalize<T>}`; | |
type MapFrom<T extends string> = `from${Capitalize<T>}`; | |
type ExtractMapperTo<Type> = { | |
[Key in keyof Type as MapTo<Key extends string ? Key : never>]: (args: lookup<Type, Key, 'dto'>) => lookup<Type, Key, 'entity'>; | |
}; | |
type ExtractMapperFrom<Type> = { | |
[Key in keyof Type as MapFrom<Key extends string ? Key : never>]:(args: lookup<Type, Key, 'entity'>) => lookup<Type, Key, 'dto'>; | |
}; | |
// Then all these mapper methods are automatically created | |
type mapper = ExtractMapperTo<DataSchema> & ExtractMapperFrom<DataSchema>; | |
// Our first goal achieved! | |
declare const m: mapper; | |
m.toClient({id: '123', name: 'John'}); | |
m.fromClient({clientId: '123', clientName: 'John'}); | |
m.toOrder({id: '123', amount: 3}); | |
m.fromOrder({orderId: '345',quantity: 4}); | |
// Derive the data type names into a union type | |
type PropToUnion<T> = {[k in keyof T]: k}[keyof T]; | |
type DataTypes = PropToUnion<DataSchema>; | |
// Second goal achieved | |
function getProcessName(c: DataTypes): string { | |
switch(c) { | |
case 'client': | |
return 'register' + c; | |
case 'order': | |
return 'process' + c; | |
default: | |
return assertUnreachable(c); | |
} | |
} | |
function assertUnreachable(x: never): never { | |
throw new Error("something is very wrong"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment