Как вызвать Symbol.iterator родительского класса из дочернего Symbol.iterator

В TypeScript у меня есть два следующих класса.

class BaseIter {
  constructor(public a: number, public b: number, public c: number, public d: number){}
  *[Symbol.iterator](): Iterator<number> {
    yield this.a
    yield this.b
    yield this.c
    yield this.d
  }
}

class MyIter extends BaseIter {
  get total() {
    return this.a + this.b + this.c + this.d
  }

  *[Symbol.iterator](): Iterator<number> {
    for(let x of this){
      yield x  
    }
    yield this.total
  }
}

const myIter = new MyIter(1, 2, 3, 4);

for (let n of myIter){
  console.log(n);
}

Класс BaseIter принимает четыре аргумента и возвращает эти четыре аргумента при повторении. У меня есть дочерний класс, который расширяет BaseIter, который должен использовать родительскую функцию итерации, но также дает дополнительное значение (общее). Текущий код не работает - он вызывает бесконечную рекурсию (повторение this вызывает ту же функцию, а не базовую функцию). Я пробовал разные методы super, но безуспешно.

Я ожидаю, что это произведет

1
2
3
4
10

Любые идеи?


person blitzmann    schedule 16.07.2019    source источник
comment
Если бы это был обычный метод, я бы просто использовал super.method().   -  person blitzmann    schedule 17.07.2019


Ответы (1)


Функции генератора имеют тип возвращаемого значения IterableIterator<T>, а не Iterator<T>. Это мешало TypeScript использовать метод из суперкласса как итеративный. В общем, вы должны позволить TypeScript вывести возвращаемое значение ваших функций, если только он не предупредит вас, что не может.

class BaseIter {
  constructor(public a: number, public b: number, public c: number, public d: number) {}

  * [Symbol.iterator] () {
    yield this.a;
    yield this.b;
    yield this.c;
    yield this.d;
  }
}

class MyIter extends BaseIter {
  get total () {
    return this.a + this.b + this.c + this.d;
  }

  * [Symbol.iterator] () {
    yield * super[Symbol.iterator]();
    yield this.total;
  }
}

const myIter = new MyIter(1, 2, 3, 4);

for (const n of myIter) {
  console.log(n);
}
person Patrick Roberts    schedule 17.07.2019
comment
хм, я думал, что получил возвращаемый тип из какого-то другого учебника по генераторам, думаю, это было неправильно? В любом случае, в этом есть смысл, спасибо! - person blitzmann; 17.07.2019
comment
@blitzmann, тип возвращаемого значения функций генератора, действительно реализует интерфейс итератора, но для этого конкретного примера важно, чтобы они также реализовали итеративный интерфейс, иначе они не являются допустимой целью оператора yield* (или цикла for...of). - person Patrick Roberts; 17.07.2019