Last active
April 21, 2020 14:18
-
-
Save roshanca/7cac34a8bfb9e05f0a3f47cf0a06d331 to your computer and use it in GitHub Desktop.
TS mixin decoration
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
class A { | |
p1() { | |
console.log('this is p1') | |
} | |
} | |
class B { | |
p2() { | |
console.log('this is p2') | |
} | |
} | |
class C { | |
p3() { | |
console.log('this is p3') | |
} | |
} | |
@mixin(A, B, C) | |
class Child {} | |
const child = new Child() | |
child.p3() | |
child.p1() | |
child.p2() | |
// this is p3 | |
// this is p1 | |
// this is p2 | |
class Foo { | |
protected makeFoo() { | |
return 'foo' | |
} | |
} | |
class Bar { | |
protected makeBar() { | |
return 'bar' | |
} | |
} | |
@mixin(Foo, Bar) | |
class FooBar { | |
public makeFoobar() { | |
return this.makeFoo() + this.makeBar() | |
} | |
} | |
const fooBar = new FooBar() | |
console.log(fooBar.makeFoobar()) // foobar |
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
/** | |
* A rigorous type alias for a class. | |
*/ | |
type Class<CtorArgs extends any[] = any[], InstanceType = {}, StaticType = {}> = { | |
new (...args: CtorArgs): InstanceType & { [K in keyof StaticType]: StaticType[K] } | |
} | |
/** | |
* Mixin decoration implementation | |
* @example @mixin(ClassA, ClassB, ClassC) | |
* class targetClass{} | |
*/ | |
function mixin(...mixins: Class[]) { | |
return (targetClass: Class) => { | |
function copyProperties<T extends U, U extends object>(target: T, source: U): void { | |
for (const key of Reflect.ownKeys(source)) { | |
if (key !== 'constructor' && key !== 'prototype' && key !== 'name') { | |
const desc = Object.getOwnPropertyDescriptor(source, key) as PropertyDescriptor | |
Object.defineProperty(target, key, desc) | |
} | |
} | |
} | |
for (const mixin of mixins) { | |
// 拷贝静态属性 | |
copyProperties(targetClass, mixin) | |
// 拷贝原型属性 | |
copyProperties(targetClass.prototype, mixin.prototype) | |
} | |
// 拦截构造器方法,进行实例属性的拷贝 | |
return new Proxy(targetClass, { | |
construct(target, args: any) { | |
const obj = new target(...args) | |
for (const mixin of mixins) { | |
copyProperties(obj, new mixin()) | |
} | |
return obj | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment