There is this Q&A about Abstract constructor types in TypeScript, which is a question I would like to know the answer to:
Abstract constructor type in TypeScript
Unfortunately, the accepted answer is little more that an unexplained one-liner: type Constructor<T> = Function & { prototype: T }
It appears that this answer is good enough for the asker, it is the accepted answer, but I'm unable to understand how the answer applies to the question.
I've tried asking in the comments, and I've tried asking someone in chat to explain the answer, but to no avail. Also, I recognize that this is only barely a different question from that one, but this is still a unique question about code.
How can I use a type of Function & { prototype: T }
to emulate an abstract class of known constructor type?
In JavaScript, all functions have a special property called
prototype
. If you use a function as a constructor (by calling it withnew
), the constructed instance will have that as its prototype. This is how classes worked in JavaScript before ES2015:ES2015 introduced the
class
syntax, which behaves the same way under the hood... and so constructor objects still have aprototype
property from which constructed instances inherit.TypeScript models this by declaring that the
Function
interface, which all functions implement, has aprototype
property of typeany
. Furthermore, when theclass
syntax is used, the constructor is still seen as aFunction
, and theprototype
property of the constructor is narrowed fromany
to the same type as the constructed class instance:Even
abstract
classes in TypeScript have aprototype
property whose type is the same as the instance type. So while you can't callnew
on an abstract class constructor, or match it to a newable type likenew() => any
, you can still talk about itsprototype
:All this means that in TypeScript a possibly-abstract class constructor is (a subtype of) a
Function
whoseprototype
property is the instance type for the constructor. Thus, you can say thatusing the intersection operator to combine
Function
and "object with aprototype
property of typeT
"...or similarly
using interface extension to achieve the same effect...
and you know that the following is valid:
That should explain how the original question's answer is applicable. Hope that helps. Good luck!