Синтаксис для повторяемого геттера?
Могу ли я объявить 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)
}