Skip to content

Instantly share code, notes, and snippets.

@sonhanguyen
Last active October 31, 2022 13:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sonhanguyen/b4a0f9432a8bb351732b22dc0d3a8104 to your computer and use it in GitHub Desktop.
Save sonhanguyen/b4a0f9432a8bb351732b22dc0d3a8104 to your computer and use it in GitHub Desktop.
kotlin's style delegate in typescript
function delegateTo(prop: string) {
const { __proto__ } = this
Object.setPrototypeOf(this,
new Proxy({}, {
get: (target, name) => {
target = this[prop]
if (name === prop) return target
if (name in __proto__) return __proto__[name]
return target ? target[name] : undefined
}
})
)
}
export type Constructor<T=any> = new(...argv) => T
export function Decorator<T=any>(prop: string) {
return <any> function() {
delegateTo.call(this, prop)
} as Constructor<T>
}
function mixin<T>(...mixins: Array<Constructor>) {
const prototype = mixins.reduce(
(props, { prototype: __proto__ }) => {
let { prototype } = props
if (prototype) props = prototype
prototype = { __proto__ }
for (const key in props) prototype[key] = props[key]
return prototype
}
)
return <any>
Object.assign(
function(...argv) {
mixins.forEach(mixin => mixin.call(this, ...argv))
},
{ prototype }
) as Constructor<T>
}
export function delegate<To, From={}>(prop: string) {
return (Class: Constructor<From>) =>
<any> class extends mixin(Class, Decorator(prop)) {
} as Constructor<To & From>
}
class A {
a() { console.log('a') }
}
@delegateTo<A>('aInst')
class B implements { aInst: A } {
constructor(private aInst: A) {}
}
new B(new A).a()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment