Here's an alternate approach you could consider:
interface NewInstance<T> {
new (...args: any[]): T;
}
function decorate()
{
return function (target: NewInstance<Object>)
{
return class ExtendedClass extends target {
public additionalProperty: string;
constructor() {
this.additionalProperty = "test2";
}
}
};
};
However, this may lead to a new issue:
// Error: Type 'typeof ExtendedClass' is
// not assignable to type 'typeof AnotherThing'.
@decorate()
class AnotherThing{
public someProp: string;
constructor() {
this.someProp = "test";
}
}
To address the error, you can try this:
function decorate()
{
return function (target: NewInstance<Object>)
{
class ExtendedClass extends target {
public additionalProperty: string;
constructor() {
this.additionalProperty = "test2";
}
}
return (<any>ExtendedClass); // casting required!
};
};
Another error may surface after that:
let anotherThing = new AnotherThing();
console.log(anotherThing.someProp);
// Property 'additionalProperty' does not
// exist on type 'AnotherThing'.
console.log(anotherThing.additionalProperty);
To resolve this, you might have to resort to using any:
console.log((<any>anotherThing).additionalProperty); // More casting!
This workaround may not be ideal. You could explore a different strategy like this:
interface NewInstance<T> {
new (...args: any[]): T;
}
function decorate()
{
return function (target: NewInstance<Object>)
{
class ExtendedClass extends target {
public additionalProperty: string;
constructor() {
this.additionalProperty = "test2";
}
}
return (<any>ExtendedClass);
};
};
function applyDecorator<T,TDecorated>(decorator, ctr): NewInstance<TDecorated> {
let decorated: NewInstance<TDecorated> = <any>decorator()(ctr);
}
interface IAnotherThing {
someProp: string;
}
interface ISomethingElse extends AnotherThing {
additionalProperty: string;
}
class AnotherThing implements IAnotherThing {
public someProp: string;
constructor() {
this.someProp = "test";
}
}
let SomethingElse = applyDecorator<IAnotherThing, ISomethingElse>(decorate, AnotherThing);
let anotherThing = new SomethingElse();
console.log(anotherThing.someProp);
console.log(anotherThing.additionalProperty);
Hope this offers some helpful insights :)