Last active
April 3, 2018 17:16
-
-
Save awinogradov/e22ef5160b1a54fd2fd72010a12689f8 to your computer and use it in GitHub Desktop.
Takie dela
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
function combineClasses<T1, T2>(C1, C2): new (...args: any[]) => T1 & T2 { | |
Object.getOwnPropertyNames(C2.prototype).forEach((name) => { | |
if (name !== 'constructor') { | |
C1.prototype[name] = C2.prototype[name]; | |
} | |
}); | |
return Object.setPrototypeOf(C2, C1); | |
} | |
function compose<T>(...args: Array<new (...args: any[]) => T>): new (...args: any[]) => T { | |
let ResultClass = args.splice(0, 1)[0]; | |
function applyMixins(mixins) { | |
for (const Mixin of mixins) { | |
ResultClass = combineClasses<T, T>(ResultClass, Mixin); | |
} | |
} | |
applyMixins(args); | |
return ResultClass; | |
} | |
describe('Compose:', () => { | |
it('should apply mixins', () => { | |
interface IMyBlock { | |
name: string; | |
} | |
class MyBlock { | |
public block = 'MyBlock'; | |
protected a: string; | |
constructor(props: IMyBlock) { | |
this.a = props.name; | |
} | |
public tag(props, state) { | |
return 'a'; | |
} | |
public attrs(props, state): any { | |
return {}; | |
} | |
} | |
class MyBlockMod11 extends MyBlock { | |
public tag(props, state) { | |
return 'b'; | |
} | |
} | |
class MyBlockMod12 extends MyBlockMod11 { | |
public tag(props, state) { | |
return 'c' + super.tag(props, state); | |
} | |
public attrs() { | |
return { id: 'the-id' }; | |
} | |
} | |
class MyBlockMod21 extends MyBlock { | |
public b: string; | |
constructor(props) { | |
super(props); | |
this.b = this.a + '1'; | |
} | |
public attrs(props, state) { | |
return { name: 'the-name', ...super.attrs(props, state) }; | |
} | |
} | |
const Test = compose(MyBlock, MyBlockMod12, MyBlockMod21); | |
const res = new Test({ name: 1 }); // должно ругаться на невалидные опции конструктору | |
expect(res.tag({}, {})).toBe('cb'); | |
expect(res.b).toBe('a1'); // НЕ должно ругаться на поле b | |
expect(res.attrs({}, {})).toMatchObject({ | |
id: 'the-id', | |
name: 'the-name', | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment