Skip to content Skip to sidebar Skip to footer

Typescript Class Variables And Error: "refers To A Value, But Is Being Used As A Type Here. . Did You Mean Typeof' ...". Why Exactly?

This works in Javascript and Typescript: class A { /* ... */ } const B = class extends A { /* ... */ } var x = new B(); console.log(x instanceof B, x.constructor.name); // true B

Solution 1:

When you write class declarations like

classA { a = 1 }

in TypeScript, you are bringing into scope two different things which are both named A. One is the value named A, a class constructor that exists at runtime. The other is the type named A, a TypeScript interface corresponding to instances of the class; such types don't exist at runtime.

Also note that a value has a type, but it is not itself a type. And the type of the A value is not A, since the class constructor is not itself an instance of the class). Instead, it has the type typeof A (expressed using TypeScript's typeof type query operator), which is similar to the type new () => A (expressed using a construct signature).

The fact that the value and type are both named A is convenient but confusing. It is convenient because it lets you use the one term A to refer to related but distinct things without requiring you to invent new terminology for each (e.g., A for the class constructor, but InstanceA for the instance type). But it is confusing because it can give the false impression that these two things are really one thing, or that the relationship between these two things is somehow inherent in the name, when it's really just incidental.


On the other hand, when you write variable declarations like

const B = classextendsA{ b = 2 };

you are only bringing into scope a value named B. There is no corresponding type named B. If you want such a type, you will have to declare it yourself:

typeB = InstanceType<typeof B>; 

The lack of an automatic type named B isn't because the compiler can't figure out that B is a class constructor. The compiler knows exactly what B is:

// const B: typeof B

And it knows that it constructs B instances:

type WhatBConstructs = InstanceType<typeof B>;
// type WhatBConstructs = B // this "B"isnot an actual type name, btw

(Here I've used the InstanceType<T> utility type to probe the type of the B constructor for its instance type.)

It's just that variable declarations name new values but not new types.

There is an existing suggestion at microsoft/TypeScript#36348 which asks that when you bind a class constructor to a variable it should also make a named type corresponding to the instance type. If this were to be implemented, then your B type would appear when you wrote const B = class extends A {...}. If you want to see this happen, you could go there and give it a 👍, but I wouldn't expect to see any changes there for the foreseeable future.


Anyway, for now, if you create both a value and a type named B manually:

const B = classextends A { b = 2 };
type B = InstanceType<typeof B>;

then things will start working for you the way you want:

var x: B = new B(); // okay

Playground link to code

Post a Comment for "Typescript Class Variables And Error: "refers To A Value, But Is Being Used As A Type Here. . Did You Mean Typeof' ...". Why Exactly?"