Reputation: 821
What signature should ctx
argument of loggerOfHidden
function have for it to work?
What 'T' could be instantiated with an arbitrary type which could be unrelated to '(Anonymous class)'
error means?
Ignoring errors it outputs just fine.
Argument of type 'this' is not assignable to parameter of type 'T & Constructor<ISayHidden>'.
Type '(Anonymous class)' is not assignable to type 'T & Constructor<ISayHidden>'.
Type '(Anonymous class)' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '(Anonymous class)'.
Type 'this' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'this'.
Type '(Anonymous class)' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '(Anonymous class)'
type Constructor<T> = new (...args: any[]) => T;
interface ISayHidden {
sayHidden(): void;
}
class Factory<T extends Constructor<Foo>> {
constructor(public Base: T) {}
ExtendSayHidden(loggerOfHidden: (ctx: T & Constructor<ISayHidden>) => void) {
return new Factory<T & Constructor<ISayHidden>>(class extends this.Base implements ISayHidden {
sayHidden() {
loggerOfHidden(this);
}
});
}
}
class Foo {
hiddenMessage = 'Wow, you found me!';
sayHi() {
console.log('Hi!');
}
sayBye() {
console.log('Bye!');
}
}
const FooExtended = new Factory(Foo).ExtendSayHidden(ctx => {
console.log(ctx.hiddenMessage);
}).Base;
let fooExtended = new FooExtended();
fooExtended.sayHidden();
EDIT: the future purpose of loggerOfHidden
will be manupulating the extended instance that is being generated by ExtendSayHidden
function. Note that Factory
can and will contain a multitude of functions, each of which will extend current Base
class further. I just want TypeScript to pretend that ctx
is no more than Foo
extended by the current class, and be able to access these field. I could create a more extensive example if needed.
EDIT2: Updated example. Can TypeScript provide ctx
with the context of the current class?
type Constructor<T> = new (...args: any[]) => T;
interface ISayHidden {
hiddenMessage: string;
sayHidden(): void;
}
class Factory<T extends Constructor<Foo>> {
constructor(public Base: T) {}
ExtendSayHidden(loggerOfHidden: <U extends Foo>(ctx: U) => void) {
return new Factory<T & Constructor<ISayHidden>>(class extends this.Base implements ISayHidden {
hiddenMessage = 'Wow, you found me!';
sayHidden() {
loggerOfHidden(this);
}
});
}
}
class Foo {
sayHi() {
console.log('Hi!');
}
sayBye() {
console.log('Bye!');
}
}
const FooExtended = new Factory(Foo)
.ExtendSayHidden(ctx => {
console.log(ctx.hiddenMessage);
}).Base;
let fooExtended = new FooExtended();
fooExtended.sayHidden();
Upvotes: 0
Views: 189
Reputation: 2610
The this
inside your anonymous class refers to the object and not the constructor.
class extends this.Base implements ISayHidden {
sayHidden() {
loggerOfHidden(this);
}
}
But you are typing it as constructor/class with T & Constructor<ISayHidden>
. Thus you need to change the typing to refer to the instantiated object of class Foo
(playground):
class Factory<T extends Constructor<Foo>> {
constructor(public Base: T) {}
ExtendSayHidden(loggerOfHidden: <U extends Foo & ISayHidden>(ctx: U) => void) {
return new Factory<T & Constructor<ISayHidden>>(class extends this.Base implements ISayHidden {
hiddenMessage = 'Wow, you found me!';
sayHidden() {
loggerOfHidden(this);
}
});
}
}
Upvotes: 2