Issue
I have a function that takes a few dependency (as an object) for a class and then declares and returns the class.
See it in the TypeScript Playground
// makeWorker.ts ---------------
function makeWorker(someDependency: any) {
return class Worker {
print() {
console.log("worker");
}
};
}
// useWorker.ts ----------------
const WorkerClass = makeWorker({
/* some dependency here */
});
Now, I want to create instance of that class like the following example where I'm using jest to test some stuff.
let worker: typeof WorkerClass;
beforeEach(() => {
worker = new Worker();
worker.print(); // this line doesn't exist in my code. it's just for demonstration
});
But then I got the error
Property 'prototype' is missing in type 'Worker' but required in type 'typeof Worker'.
Property 'print' does not exist on type 'typeof Worker'.(2339)
Edit
I know that, if we want to declare a variable as an instance of a certain class then we need to write let var: TheClassName;
. But the reason I used typeof WorkerClass
because if I use let worker: WorkerClass;
then I get the following error.
'WorkerClass' refers to a value, but is being used as a type here. Did you mean 'typeof WorkerClass'?(2749)
End Edit
After working with it a little bit, I discovered that the following snippet doesn't raise any error.
const worker = new WorkerClass();
worker.print();
So I thought, may be I'm not getting the type of WorkerClass
correctly and I tried the following but it didn't help. I got the same error again.
let worker: ReturnType<typeof makeWorker>;
worker = new worker();
worker.print();
Finally, I was browsing through the docs of Utility Types and randomly tried the utility type InstanceType
on the WorkerClass
and it worked on the first try!
let worker: InstanceType<typeof WorkerClass>;
worker = new WorkerClass();
worker.print();
Now my question is: why I can't use the WorkerClass
in variable declaration and what the InstanceType
is actually doing in the last example that it doesn't raise any error.
Thanks in advance <3
Solution
InstanceType
makes use of type inferration. Basically, it allows you to take data from a given type that matches the given pattern. This can only be used in conditional clauses. A basic example of this is the following code:
type Foo = { hello: "world"; } extends { hello: infer Hello } ? Hello : never; // "world"
As you can see, we get the value of hello
from the object by inferring the property.
Now, in the case of InstanceType
, it uses type inferration on the constructor methods:
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
The abstract new (...args: any) => any
is basically just the type for a constructor that has any arguments and returns a type of any. Then, it infers the return type from the given constructor function using infer R
. I hope this helps explain how this works for you.
Answered By - sno2
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.