Matthew Layton
Matthew Layton

Reputation: 42390

TypeScript - expressing types/constructors vs. instances of types

Types

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);

Instances

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

Answers (1)

jcalz
jcalz

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

Related Questions