Daz Daz - 2 months ago 15
TypeScript Question

Typescript Interfaces implementing Iterator<T>

I am trying to understand if this is possible...

export interface ISomething { ... }
export interface ISomethingElse implements Iterator<ISomething> { ... doSomeJob(): void; ... }


The idea is that when i declare my class, ClassA i can do something like this...

export ClassA implements ISomethingElse {

public doSomeJob(): void {
for (let item of this) {
console.log(item);
}
}

}


I'm looking to implement something that behaves like this declaration in C#

public interface ISomethingElse : IEnumerable<ISomething> {
void DoSomeJob();
}

Answer

If you want to use Iterator then you can do this:

interface ISomething { }

interface ISomethingElse extends Iterator<ISomething> {
    doSomeJob(): void;
}

class ClassA implements ISomethingElse {
    private counter: number = 0;

    public next(): IteratorResult<ISomething>{
        if (++this.counter < 10) {
            return {
                done: false,
                value: this.counter
            }
        } else {
            return {
                done: true,
                value: this.counter
            }
        }

    }

    public doSomeJob(): void {
        let current = this.next();
        while (!current.done) {
            console.log(current.value);
            current = this.next();
        }
    }
}

(code in playground)

But if you want to use the for/of loop then you'll need to use Iterable:

interface ISomethingElse extends Iterable<ISomething> {
    doSomeJob(): void;
}

class ClassA implements ISomethingElse {
    [Symbol.iterator]() {
        let counter = 0;

        return {
            next(): IteratorResult<ISomething> {
                if (++this.counter < 10) {
                    return {
                        done: false,
                        value: counter
                    }
                } else {
                    return {
                        done: true,
                        value: counter
                    }
                }
            }
        }
    }

    public doSomeJob(): void {
        for (let item of this) {
            console.log(item);
        }
    }
}

(code in playground)

But you'll need to target es6, otherwise you'll get an error in the for/of loop (like in playground):

Type 'this' is not an array type or a string type

You can find more information about this here:
Iterators and generators
and here:
Iteration protocols