Reputation: 42390
We could express using a type alias that we expect a type to be passed as an argument, like so:
type Type<T> = {
readonly prototype: T
}
function getTypeArg<T>(t: Type<T>): void {
...
}
This fails because 123
is a primitive/instance and therefore doesn't have a prototype property.
getTypeArg(123);
This passes because it's a type and therefore has a prototype property.
getTypeArg(Number);
The same is not so easy for instances.
function getInstance(inst: any): void {
...
}
Allows any instance to be passed
getInstance(123);
getInstance("Hello World");
But this also allows types to be passed, which we don't want
getInstance(String);
we should be able to fix this with a type alias
type Instance = {
constructor: Function;
}
function getInstance(inst: Instance): void {
...
}
But this doesn't work, so the question is, why?
Upvotes: 4
Views: 77
Reputation: 330411
Terminology note: What you're calling a "type" would better be described as a "constructor". The word "type" has a bunch of meanings, and in TypeScript you'd usually use it to mean something that does not exist as a runtime value at all. Best to use "constructor", I think.
Anyway, the reason why it doesn't work is because all objects have a constructor
property, even constructors:
console.log(String.constructor === Function) // true
I think only null
and undefined
fail to match your Instance
interface. If you really intend to exclude constructors, it would be better to define Instance
as "a thing with no prototype
", like this:
type Instance = {
constructor: Function;
prototype?: never; // prototype can be missing or undefined, that's it
}
And it should work more like what you intend:
getInstance(123); // okay
getInstance("Hello World"); // okay
getInstance(String); // error as desired
getInstance(null); // error as desired I hope
getInstance(undefined); // error as desired I hope
Hope that helps; good luck.
Upvotes: 5