Created
January 25, 2023 21:19
-
-
Save svallory/59cf4fb527ffeedb5fc03fbd388aac7c to your computer and use it in GitHub Desktop.
Magic catch-all method in Typescript class by extending Javascript Proxy class to build the perfect Value Object base class
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
type Setters<Type> = { | |
[Property in keyof Type as `set${Capitalize<string & Property>}`]: (newValue: Type[Property]) => Type & Setters<Type> | |
}; | |
abstract class VO<T> { | |
constructor( | |
public readonly type: any, | |
public readonly excludedProperties: string[], | |
) { | |
return (new Proxy(this, { | |
apply: (target, thisArg, argArray) => { | |
if (!thisArg.hasOwnProperty(target)) { | |
throw new Error(`Method ${target} is not defined on ${thisArg}`); | |
} | |
return thisArg[target](...argArray); | |
} | |
}) as unknown as VO<T> & Setters<T>); | |
} | |
} | |
class InviteeVO extends VO<InviteeVO> { | |
constructor( | |
public readonly name: string, | |
public readonly email: string, | |
public readonly invite: number, | |
) { | |
super(Invitee, ['name', 'status', 'invite']); | |
return (this as unknown as InviteeVO & Setters<InviteeVO>); | |
} | |
} | |
type InviteeSetters = Setters<InviteeVO>; | |
export const Invitee: typeof InviteeVO & InviteeSetters = InviteeVO as any; | |
const john = new InviteeVO('John Snow', '[email protected]', 1) as InviteeVO & InviteeSetters; | |
const arya = john.setName('Arya Stark').setInvite(2); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment