Search code examples
javascripttypescriptclassstaticstatic-methods

Access a object's class's static methods in Typescript?


class Base {
  static f(){console.log('Base')}
}

class A extends Base {
  static f(){console.log('A')}
}

class B extends Base {
  static f(){console.log('B')}
}

let obj: A|B = new A()

obj.<what to put here>.f()

I don't know the exact class for obj, I need to print A or just call f() for correct class of obj.

I don't need just the class name, that is for example. I am doing more complex things.

prototype, typeof, constructor all seem to be syntax errors.


Solution

  • Both Object.getPrototypeOf() (replacement to the now deprecated Object.prototype.__proto__) or Object.prototype.constructor should work:

    Object.getPrototypeOf(obj).constructor.f();
    
    obj.constructor.f();
    

    Actually:

    Object.getPrototypeOf(obj).constructor === obj.constructor; // true
    

    Here you can see the compiled source in action:

    class Base {
      static f() { console.log('Base'); }
    }
    
    class A extends Base {
      static f() { console.log('A'); }
    }
    
    class B extends Base {
      static f() { console.log('B'); }
    }
    
    const objBase = new Base();
    const objA = new A();
    const objB = new B();
    
    Object.getPrototypeOf(objBase).constructor.f();
    objBase.constructor.f();
    
    Object.getPrototypeOf(objA).constructor.f();
    objA.constructor.f();
    
    Object.getPrototypeOf(objB).constructor.f();
    objB.constructor.f();
    
    console.log(Object.getPrototypeOf(objB).constructor === objB.constructor);
    console.log(Object.getPrototypeOf(objB) === B.prototype);
    .as-console-wrapper {
      max-height: none !important;
    }

    Note static properties exist in classes but not in instances.

    Therefore, if you want to go from obj to its prototype, you should call Object.getPrototypeOf(obj), not obj.prototype, which is a completely different thing.

    The .prototype property only exists in functions and, when instantiating a new object using new and a call to that constructor function (new A()), will become the newly created object's prototype (the deprecated .__proto__).

    In your example:

    obj.prototype;                // undefined
    A;                            // class A { static f() { ... } }
    A.protoype;                   // { constructor: class A { ... } }
    A.protoype.constructor;       // class A { static f() { ... } }
    A.protoype.constructor === A; // true
    obj.constructor;              // class A { static f() { ... } }
    obj.constructor === A;        // true
    
    Object.getPrototypeOf(obj) === A.prototype; // true