1
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.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Sid Datta
  • 1,110
  • 2
  • 13
  • 29
  • Are you guaranteed that `obj` is either an instance of `A` or `B`? – Nick Oct 29 '19 at 00:30
  • Possible duplicate of [How to get the parent class at runtime](https://stackoverflow.com/questions/36867005/how-to-get-the-parent-class-at-runtime) –  Oct 29 '19 at 00:30
  • `Object.getPrototypeOf(obj).constructor.f();` works for me –  Oct 29 '19 at 00:31
  • 1
    `obj.constructor.f()` is not a syntax error for sure. Did you mean you're getting a type error? If so, which one? – Bergi Oct 29 '19 at 00:33
  • Typescript thinks `obj.constructor` is a `Function` hence shows an error, but works correctly when cast as ``. `Object.getPrototypeOf(obj).constructor.f()` works. – Sid Datta Oct 29 '19 at 18:05

1 Answers1

2

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
Danziger
  • 19,628
  • 4
  • 53
  • 83
  • 1
    Thanks, these solutions worked. Typescript thinks `obj.constructor` is a `Function` hence shows an error, but works correctly when cast as ``. – Sid Datta Oct 29 '19 at 17:57