I've been trying to understand if there is any difference between using InstanceType
to assign a type, or simply using the Class name.
In particular, given the class:
MyClass {
public static foo: string = 'abc'
public makeFoo() {
// awesome maker
}
}
When I want to use an instance of the class, it seems that there is no difference between:
// inside some other Class
private myClassInstance: InstanceType<typeof MyClass>
...
this.myClassInstance = new MyClass()
and
// inside some other Class
private myClassInstance: MyClass
...
this.myClassInstance = new MyClass()
At least in VSCode I don't get any visible difference in using any of the two. However I guess a difference must exist, if TS has implemented InstanceType<>
.
Anyone knows if there is a difference?
Anyone knows if there is a difference?
No, there is no difference. But you have to use InstanceType
in some cases.
The InstanceType
helper type exists because a class name can represent two things:
prototype
of the constructor function and optionally some instance fields)In TypeScript, when you declare a class
, you declare both of them: the constructor function (thus its type) and the type of the generated instances (class fields and methods).
In your example, you are declaring:
MyClass
: a kind of interface which contains the class fields and methods.typeof MyClass
: the constructor function. (in this case MyClass
refers to the runtime class)As you didn't specify a constructor function, its type is new () => MyClass
and you can extract the type MyClass
from it thanks to InstanceType
.
As a real-world example, imagine you are trying to implement a factory (function that returns instances of classes). One naive implementation would look like this:
declare function factory<T>(ctor: T): T;
class A { }
const res = factory(A);
// ^ this gives `res: typeof A`, which is NOT an instance type.
While TypeScript doesn't give an error, you are telling TypeScript to treat res
as the constructor function of A
instead of the instance of A
.
However, this implementation works:
type Constructor = new (...args: any[]) => any;
declare function factory<T extends Constructor>(ctor: T): InstanceType<T>;
class A { }
const res = factory(A);
// ^ this gives `res: A`, as expected.
Because InstanceType
extracted the return type.