Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: static properties and inheritance

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!

like image 950
KorHosik Avatar asked Jun 09 '16 17:06

KorHosik


2 Answers

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)

like image 198
Nitzan Tomer Avatar answered Sep 19 '22 15:09

Nitzan Tomer


I understand the warning and it's totally right from a TypeScript point of view

Right - this is something like inheritance, but it doesn't and shouldn't generally work for your static properties. To get around this, disable typechecking using any:

alert((<any>this.constructor).Items.FOO);

This situation often occurs when converting old js code, but should be avoided when writing new TS code. If you want to do this correctly you would need to (as you are probably aware) implement and override a getItems or similar method in your two classes to return the corresponding Items, and call that method from show.

like image 34
mk. Avatar answered Sep 18 '22 15:09

mk.