Skip to content

Instantly share code, notes, and snippets.

@kuboon
Created May 7, 2026 06:06
Show Gist options
  • Select an option

  • Save kuboon/3e7756ce318052c07b66f458773f5afb to your computer and use it in GitHub Desktop.

Select an option

Save kuboon/3e7756ce318052c07b66f458773f5afb to your computer and use it in GitHub Desktop.
trait & impl for typescript
type ImplType<I, M, O> = I & ThisType<I & M & {owner: O}>
type ImplFor<X, O = never> = <I, M = X>(trait: ImplType<I, M, O>) => (model: M, owner?: O) => I & M & {owner: O}
// simple but slow
const MutableImpl = <I, M, O>(trait: ImplType<I, M, O>) =>
(model: M, owner?: O) =>
Object.setPrototypeOf(model, Object.assign(trait, {owner}))
// better performance
const CopyImpl = <I, M extends Record<string, unknown>, O>(impl: ImplType<I, M, O>) => (model: M, owner?: O) => {
const pdesc: PropertyDescriptorMap = {}
Object.entries(model).forEach(([k, value])=>{ pdesc[k] = {value, writable: true, enumerable: true}})
pdesc['owner'] = {value: owner, writable: false, enumerable: false}
return Object.create(impl, pdesc);
}
const ImplFor = CopyImpl
// types
type User = {name: string, age: number}
type Group = {id: string, users: User[]}
// impl for User
const userImplGen: ImplFor<User, Group> = ImplFor
const userImpl = userImplGen({
getName(){ return this.name },
addAge(){ this._test += this.age },
_test: 0,
get test() { return this._test },
usersCount() { return this.owner.users.length }
})
type UserImpl = ReturnType<typeof userImpl>
// impl for Group
const groupImplGen: ImplFor<Group> = ImplFor
const groupImpl = groupImplGen({
get userModels(){ return this.users.map((x: User)=>userImpl(x, this))}
})
// data
const user: User = {name: 'namae', age: 17}
const group: Group = {id: 'test', users: [user]}
// binding
const groupModel = groupImpl(group)
console.log(groupModel.users)
console.log(groupModel.userModels[0].usersCount())
@kuboon
Copy link
Copy Markdown
Author

kuboon commented May 7, 2026

なんで owner 作るのにこだわったのか忘れた

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment