Home > database >  Local type definition for nested classes
Local type definition for nested classes

Time:03-13

I'm playing with nested classes in Typescript/Javascript to model what is possible in Java. This works pretty well. I can have static and non-static nested classes, derive from each other and so on. This is my test declaration:

class OuterClass {
    public static InnerClass2 = class InnerClass2 {
        public static InnerClass3 = class InnerClass3 {

        };

        public update(o: OuterClass): void {
            o.a = "b";
        }
    };

    public InnerClass1 = (($outer) => {
        class InnerClass1 {
            public static InnerClass3 = class InnerClass3 {

            };

            public update(): void {
                $outer.a = "b";
            }

        }

        return InnerClass1;
    })(this);

    public InnerClassDerived = (($outer) => {
        class InnerClass extends this.InnerClass1 {
            public constructor() {
                super();

                this.update();
            }

        }

        return InnerClass;
    })(this);

    private a = "a";

    private list: Array<InstanceType<typeof this.InnerClass1>> = [];

    public test(): void {
        const i = new this.InnerClass1();
        this.list.push(i);
        i.update();
    }
}

What bothers me, however, is this line:

private list: Array<InstanceType<typeof this.InnerClass1>> = [];

because of the long type description for the array. If InnerClass1 were static I could define a type for it in a separate namespace, like for InnerClass2:

export namespace OuterClass {
    export type InnerClass2 = InstanceType<typeof OuterClass.InnerClass2>;
}

But that's not possible, as I need that this qualifier. Local type definitions in classes are not possible from what I know, so how could a possible solution look like to avoid the lengthy type in the array type declaration?

Ideally I would like to have this:

private list: this.InnerClass1[] = [];

CodePudding user response:

You were quite close to the solution. Instead of returning the class definition in the factory class properties, you should instead return a class expression. Then, you can access the type of InnerClass1 via OuterClass["InnerClass1"]

class OuterClass {
    public static InnerClass2 = class InnerClass2 {
        public static InnerClass3 = class InnerClass3 {

        };

        public update(o: OuterClass): void {
            o.a = "b";
        }
    };

    public InnerClass1 = (($outer) => {
      return class InnerClass1 {
        public static InnerClass3 = class InnerClass3 {

        };

        public update(): void {
            $outer.a = "b";
        }
      };
    })(this);

    public InnerClassDerived = (($outer) => {
        return class InnerClass extends this.InnerClass1 {
            public constructor() {
                super();

                this.update();
            }

        }
    })(this);

    private a = "a";

    private list: Array<OuterClass.classes.InnerClass1> = [];

    public test(): void {
        const i = new this.InnerClass1();
        this.list.push(i);
        i.update();
    }
}

export declare namespace OuterClass {
    export namespace classes {
        export type InnerClass1 = InstanceType<OuterClass["InnerClass1"]>;
        export type InnerClass2 = InstanceType<typeof OuterClass["InnerClass2"]>;
    }
}

TypeScript Playground Link

  • Related