This is the simplified code
export interface MyInterface{
// Have no idea why I need an export here.
// If I remove it, it gives
// semantic erro
Add a type definition for MyClass
const MyClass = createClass();
type MyClass = InstanceType<typeof MyClass>
Consider the flowing simple class declaration:
class MyClass {}
const mc: MyClass = new MyClass()
When you declare a class with the class
keyword, the compiler knows two things. That in the current scope there is a value with the name of the class that is capable of constructing the class (ie the MyClass
constructor) and that a type with the same name as the class will also exist in the current scope representing the instance type for the class (in this case the MyClass
type). See this answer for value space vs type space.
Since you declare the class in a function even if you were to give it a name it would only be accessible inside the function (basic scoping rules). The interface is accessible as it is in the same scope (assuming everything is in the same file) or is explicitly imported (if you are in another module).
When you use the returned function and assign it to a const
(const MyClass = createClass();
) you are only doing half of what a class
declaration would do, you are telling the compiler that a constructor named MyClass
exists. The compiler will add no type for the instance type of MyClass
(why would it, an assignment of a const
does not usually introduce new types, just new values).
The simple solution is to do the other half of the job, add a type with the same name that will be the instance type for the returned class. The two names will not collide, as one is in value space (the const
) the other in type space (the type
)
const MyClass = createClass();
type MyClass = InstanceType<typeof MyClass>
const mc: MyClass = new MyClass(); // Ok now.
Note I am assuming you are declaring the class inside a function and returning it with a reason that is not obvious from the question, if you are not just use a class declaration instead.
TS2451 Cannot redeclare block-scoped variable 'createClass'
This error occurs because you have createClass
function somewhere else in your ambient environment. Ambient means, not scoped by modules. Writing at least one import
or export
scopes your file, i.e. makes it a module.
Instead of exporting random interface you could just do this: export {}
in the end of the file.
const MyClass = createClass(); const mc: MyClass
In the above code you are mixing types with values. Specifically, MyClass
is a value here and you are trying to use it as a type.
Overall, you are doing weird things by returning a class by a function. I know you might have your own reasons for that, but normally you should write that code like this:
class MyClass {}
const mc: MyClass = new MyClass() // thought the type annotation is not necessary