Unexpected behavior in [Symbol.iterator]
LviatYi opened this issue · comments
I have a type that implements [Symbol.iterator]:
class IteratorTest {
// This is just a simple replacement for the data structure that needs to be traversed.
// It may actually be a tree or other data structure implemented by a custom traversal.
nums: number[] = [1, 2, 3, 4, 5];
public [Symbol.iterator](): Iterator<number> {
let idx = 0;
return {
next: (): IteratorResult<number> => {
if (idx < this.nums.length) {
return {
value: this.nums[idx++],
done: false,
};
} else return {
value: undefined,
done: true,
};
},
};
}
}
Enumerable returns an empty array when I try to use it like this:
// in linq.d.ts export function from<T>(obj: Iterator<T>): IEnumerable<T>;
// so I called:
Enumerable.from(et[Symbol.iterator]()).toArray()
The reason is that during the construction of Enumerable.from():
// linq.js
if (typeof obj != Types.Function) {
// array or array-like object
if (typeof obj.length == Types.Number) {
return new ArrayEnumerable(obj);
}
// iterable object
if (typeof Symbol !== 'undefined' && typeof obj[Symbol.iterator] !== 'undefined') { // use obj as who has [Symbol.iterator]
return new Enumerable(function () {
return new IEnumerator(
Functions.Blank,
function () {
var next = obj.next(); // use obj as iterator
return (next.done ? false : (this.yieldReturn(next.value)));
},
Functions.Blank);
});
}
}
I'm not a typescript expert, but I think this code is dealing with Iterator. obj
itself is an Iterator, but here we still try to access obj.[Symbol.iterator]
.
Then it tries to access obj.next()
in the iteration, which is no problem because obj
as an Iterator contains a next
function.
So I had to change my code to this to get it to work properly:
class ETest {
nums: number[] = [1, 2, 3, 4, 5];
public [Symbol.iterator](): Iterator<number> {
let idx = 0;
return {
next: (): IteratorResult<number> => {
if (idx < this.nums.length) {
return {
value: this.nums[idx++],
done: false,
};
} else return {
value: undefined,
done: true,
};
},
// A useless function just to pass the `typeof obj[Symbol.iterator] !== 'undefined'` predicate
[Symbol.iterator](): Iterator<number> {
return {
next(...args): IteratorResult<number, any> {
return undefined;
},
};
},
};
}
}
Is there anything wrong with my usage? In my opinion, the former should be the correct usage of from<T>(obj: Iterator<T>): IEnumerable<T>
Resolved in version 4.0.3