anandaravindan
anandaravindan

Reputation: 2551

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

Upvotes: 41

Views: 55101

Answers (4)

Benny Code
Benny Code

Reputation: 54995

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.

Upvotes: 11

Willem van der Veen
Willem van der Veen

Reputation: 36680

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);

Upvotes: 1

vossad01
vossad01

Reputation: 11958

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.

Upvotes: 8

Bergi
Bergi

Reputation: 665574

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++;
    }   
}

Upvotes: 50

Related Questions