How to extend TypeScript knowledge of the new inheritances?

Viewed 40

How to make TypeScript to be aware of all inheritances that happened in Base variable of Factory class, so I can get no errors. It should definitely be possible because I get the result at the end, but Property 'X' does not exist on type 'Rect' errors are thrown.

interface IPrintable {
    print(): void;
}

interface ILoggable {
    log(): void;
}

class Factory<T extends new (...args: any) => IShape> {
    constructor(public Base: T) {}

    Printable() {
        this.Base = class extends this.Base implements IPrintable {
            print() {
                console.log(`${this.x}:${this.y}`);
            }
        }

        return this;
    }

    Loggable() {
        this.Base = class extends this.Base implements ILoggable {
            log() {
                console.log(`${this.x}:${this.y}`);
            }
        }

        return this;
    }
}

interface IShape {
    x: number,
    y: number
}

class Rect implements IShape {
    constructor(
        public x: number,
        public y: number
    ) {}
}

const RectMaxed = new Factory(Rect).Printable().Loggable().Base;
const rectMaxed = new RectMaxed(10, 20);
rectMaxed.print();
rectMaxed.log();
1 Answers

You will need to create a new instance of the factory every time when adding a method. Try out this code:

interface IPrintable {
    print(): void;
}

interface ILoggable {
    log(): void;
}

type Constructor<T> = new (...args: any[]) => T;

class Factory<T extends new (...args: any) => IShape> {
    constructor(public Base: T) {}

    Printable() {
        return new Factory<T & Constructor<IPrintable>>(class extends this.Base implements IPrintable {
            print() {
                console.log(`${this.x}:${this.y}`);
            }
        });
    }

    Loggable() {
        return new Factory<T & Constructor<ILoggable>>(class extends this.Base implements ILoggable {
            log() {
                console.log(`${this.x}:${this.y}`);
            }
        });
    }
}

interface IShape {
    x: number,
    y: number
}

class Rect implements IShape {
    constructor(
        public x: number,
        public y: number
    ) {}
}

const RectMaxed = new Factory(Rect).Printable().Loggable().Base;
const rectMaxed = new RectMaxed(10, 20);
rectMaxed.print();
rectMaxed.log();

I added a new type Constructor<T> which indicates a class. You can also try it here.

Related