可迭代 getter 的语法?

Syntax for iterable getter?

我可以声明 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!";
        }
    }
}

TypeScript 或 JavaScript 中没有这样的语法。 getter 应该 return 一个迭代器:

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

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

这可以通过装饰器解决,但由于 class 装饰器不支持突变,因此应手动处理正确的输入:

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