TypeScript: static properties and inheritance

KorHosik picture KorHosik · Jun 9, 2016 · Viewed 8.6k times · Source

I'm quite new to TypeScript (1.8) and I have a small issue with inheritance and static properties.

Please find below the test code I'm currently running:

class A {
    public static Items = {
        FOO: 'A'
    };

    public show() {
        alert(this.constructor.Items.FOO);
    }
} 

class B extends A {
    public static Items = {
        FOO: 'B'
    };
}

var a = new A();
var b = new B();

a.show(); // alert "A"
b.show(); // alert "B"

TypeScript Playground link

This code runs fine and the two alerts are shown as expected.

BUT the TypeScript compiler throws an error : Property "Items" does not exist on type "Function"

I understand the warning and it's totally right from a TypeScript point of view, but how can I achieve the same result while making the compiler happy? this.Items.FOO obviously does not work and I didn't find a self equivalent or something like that...

Am I missing something?

Thanks in advance!

Answer

Nitzan Tomer picture Nitzan Tomer · Jun 9, 2016

There was a similar question today: Referencing class without name to use different static method in subclasses in TypeScript.

There's a discussion/suggestion of having this.constructor returning the right type here: T.constructor should be of type T.

As for possible solutions for you for now:

Without static at all:

class A {
    public show() {
        alert(this.getItems().FOO);
    }

    protected getItems() {
        return {
            FOO: 'A'
        }
    };
}

class B extends A {
    protected getItems() {
        return {
            FOO: 'B'
        }
    }
}

(code in playground)

Static with typeof:

class A {
    public static Items = {
        FOO: 'A'
    };

    public show() {
        alert((<typeof A | typeof B> this.constructor).Items.FOO);
    }
}

(code in playground)

Static with constructor interface:

interface AConstructor {
    new (): A;
    Items: any;
}

class A {
    public static Items = {
        FOO: 'A'
    };

    public show() {
        alert((this.constructor as AConstructor).Items.FOO);
    }
}

(code in playground)