typescriptstatic-methodstemplate-method-pattern

Calling static method from non-static method in Typescript


I have some static stuff in all my hierarchy (in this example, the _image). I would want to be able to access the correspondant _image without having to repeat the code:

This would be great:

class Actor {
    static _image; // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(this.class._image); //doesn't work....
    }
}

class GoodActor extends Actor {
    static _image = 'good.png'
}

class BadActor extends Actor {
    static _image = 'bad.png'
}

class MediumActor extends Actor {
    static _image = 'medium.png'
}

But it doesn't work. Right now I only got to:

class Actor {
}

class GoodActor extends Actor {
    static _image = 'good.png'  // I need it to be static

    method show(){   // I need it to be non-static
        this.setImage(GoodActor._image);
    }
}

class BadActor extends Actor {
    static _image = 'bad.png'  // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(BadActor._image);
    }
}

class MediumActor extends Actor {
    static _image = 'medium.png'  // I need it to be static

    method show(){  // I need it to be non-static
        this.setImage(MediumActor._image);
    }
}

Suppose those four classes have more methods. I don't want to have to repeat the show() method in every subclass... Yet I need the show() method to be non static and the _image to be statically accessed.

I have read this issue https://github.com/Microsoft/TypeScript/issues/7673 but unfortunatelly I can't ask there as they have closed it without fixing it. None of them talked about this problem of needing to dynamically resolve the static method to be invoked.


Solution

  • Update: Why don't you want to construct the individual objects prior to caching images? If you make construction inexpensive, there's no benefit of using static fields.

    Example:

    class Actor {
        image: string;
    
        showImage() {
            console.log(this.image);
        }
    }
    
    
    class GoodActor extends Actor {
        image = 'good.png';
    }
    
    class BadActor extends Actor {
        image = 'bad.png';
    }
    
    const myActorTypes: (typeof Actor)[] = [GoodActor, BadActor];
    
    function preloadImages() {
        for (let myActorType of myActorTypes) {
            preloadImage(new myActorType().image);
        }
    }
    
    function preloadImage(image: string) {
        console.log(`Loading ${image}`);
    }
    
    preloadImages();
    
    // "Loading good.png"
    // "Loading bad.png"