How to use generator function in typescript
I am trying to use generator function in typescript. But the compiler throws error
error TS2339: Property 'next' does not exist on type
Below is an closest sample of my code.
export default class GeneratorClass {
constructor() {
this.generator(10);
this.generator.next();
}
*generator(count:number): Iterable<number | undefined> {
while(true)
yield count++;
}
}
Here is the playground link for the same
The next
method exists on the generator that the function returns, not on the generator function itself.
export default class GeneratorClass {
constructor() {
const iterator = this.generator(10);
iterator.next();
}
*generator(count:number): IterableIterator<number> {
while(true)
yield count++;
}
}
I was seeing this error because my tsconfig.json was targeting es5
.
I simply changed (excerpted) from:
"target": "es5",
"lib": [
"es5",
"es2015.promise"
]
to:
"target": "es6",
"lib": [
"es6"
]
and the error went away.
Note: For VS Code I needed to reload the window for IntelliSense to recognize the change.
To solve the problem, it is very important to know the differences between generator functions (generators for short) and their return values.
A generator function (marked by the asterisk) is a function, which returns a generator object. The generator object fulfills the requirements of an iterator and an iterable.
Iterators have a next
method (that's the method you are looking for in your question). And iterables have a property called Symbol.iterator
(specifying a default iterator), which makes them usable in for-loops.
Because a generator function returns a generator object and a generator object is an iterable iterator, you have to declare a return type of IterableIterator
. In your case it will be IterableIterator<number>
.
Because the terms here are confusingly similar, I have recorded a Generator tutorial which explains the differences. Make sure to set your target
to es6
in your tsconfig.json
, when using generator functions.
Here is another example which uses the Generator type of typescript. Some of the types at the assignment of iterators e.g. const iterator: Generator<number>
can be omitted since TS can infer them. However I included them in this example to be more explicit.
class GeneratorClass {
*generator(count:number): Generator<number> {
while(count < 3)
yield count++;
}
}
const generatorObject = new GeneratorClass();
// Getting our generator object which we can use as an iterator.
const iterator: Generator<number> = generatorObject.generator(1);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
/*
[LOG]: {
"value": 1,
"done": false
}
[LOG]: {
"value": 2,
"done": false
}
[LOG]: {
"value": undefined,
"done": true
}
*/
// Alternative more clean for of syntax.
// For of can iterate over any iterable
// Can be used since every Generator is an Iterator
const iterator2: Generator<number> = generatorObject.generator(1);