I'm very new to TypeScript and having a hard time figuring a problem.
Let's say I have a function that yields another function like below.
function sayHello() {
return {
name: 'mike'
}
};
function* test() {
yield(sayHello);
}
I'm trying to access name
property in my test, but getting the following error message.
Property 'name' does not exist on type 'void | (() => { name: string; })'. Property 'name' does not exist on type 'void'.
This is my test code
const a = test();
a.next().value.name
Is there a way to indicate that value
object is returned from sayHello
function?
The issue that you are facing is the way yield
works. Here is the MDN doc with a nice example.
Bottom line, when you call next
of the generator, the function pauses and returns whatever is on the yield
keyword, and resumes again when we call next
again, only to pause on the next yield
until the function returns eventually.
In your case,
function* test() {
yield(sayHello);
}
You have two stops, one when function yields at line #2 and returns the function, the next time the function's natural return which is void
. So, your function may return either the function or void
, hence the return type as you correctly pointed is:
void | (() => { name: string; })
Let's see the problem, with this information. When you say,
const a = test();
const value = a.next().value
Typescript cannot guarantee whether value is the function or void, because it does not track the the number of times next() is called and which next()
would result into the function and which into void
. So, the responsibility is on the developer.
This is how you do it:
function sayHello() {
return {
name: 'mike'
}
};
function* test() {
yield(sayHello);
}
const a = test();
const v = a.next().value;
// We need to ensure that this v is not void,
// which leaves it being the function
if(v){
const r = v().name;
console.log(r) // works!
}
// Now that it has yielded, this would be undefined
console.log(a.next().value)
Link to TS Playground: https://tsplay.dev/mL9VbW