Синтаксис для повторяемого геттера?

Могу ли я объявить getter, который ведет себя как генератор функций?

Мои попытки

class Foo {
    * Test1(): IterableIterator<string> { // Works, but not a getter...
        yield "Hello!"; 
    }

    * get Test2(): IterableIterator<string> { // Syntax error
        yield "Hello!"; 
    }

    get * Test3(): IterableIterator<string> { // Syntax error
        yield "Hello!"; 
    }

    get Test4(): IterableIterator<string> { // Works, but ugly syntax...
        return function* (): IterableIterator<string> {
            yield "Hello!";
        }();
    }
}

Например, в C# это совершенно правильно...

class Foo
{
    IEnumerable<string> Test
    {
        get
        {
            yield return "Hello!";
        }
    }
}

1 ответ

Решение

В TypeScript или JavaScript такого синтаксиса нет. Получатель должен вернуть итератор:

class Foo {
    private * _bar() {
        yield "Hello!"; 
    }

    get bar(): IterableIterator<string> {
        return this._bar();
    }
}

Это может быть решено с помощью декоратора, но поскольку мутация классов не очень хорошо поддерживается в декораторах, правильная типизация должна выполняться вручную:

function get<T>(getter: keyof T) {
    return (target: any, method: string, descriptor?: any) => {
        Object.defineProperty(target, getter, {
            configurable: true,
            enumerable: false,
            get() {
                return this[method]();
            }
        });
    }; 
}

interface Foo {
    bar: IterableIterator<string>;
}
class Foo {
    @get<Foo>('bar')
    private * _bar() {
        yield "Hello!"; 
    }
}

Что ж, вы можете сделать этот трюк, если не хотите создавать метод частного генератора:

class WithIterableGetter {
  a: string
  b: string
  constructor() {
    this.a = 'abc'
    this.b = 'bcd'
  }

  get getter(): IterableIterator<string> {
    let i = 0;
    let self = this;
    return {
      next: function() {
        return {
          done: i > 1,
          value: self[i++ === 0 ? 'a' : 'b']
        };
      },
      [Symbol.iterator]: function() { return this; }
    }
  }
}

for (const i of new WithIterableGetter().getter) {
  console.log(i)
}
Другие вопросы по тегам