Allow NodeList in for-of loop ES5 mode
saschanaz opened this issue ยท 8 comments
NodeList
interface is defined as iterable in DOM4, but by design it cannot be directly used in for-of loop because we cannot declare it as iterable in ES5.
Suggestion
Introduce a ES5-compatible way to declare iterable interfaces (Similar to what discussed in #2862)
// WebIDL-like way
interface NodeList {
iterable<Node>
}
// extends-like way
interface NodeList iterable<Node> {}
iterable<T>
in ES6 mode will work as a shorthand of [Symbol.iterator](): IterableIterator<T>
but in ES5 mode will just make an internal flag to be allowed in for-of loop.
// NodeList is marked as iterable,
// it has .length property and index signature for ES5 emit, so all good
for (let node of document.querySelectorAll("...")) {
}
This will make it work both on ES5 and ES6 without changing emit.
I get around this by using the dom4 library and declaring typings that make NodeListOf
extend Array
:
interface NodeListOf<TNode extends Node> extends Array<TNode> {}
for (let el of document.querySelectorAll("p")) {
//
}
I get around this by using the dom4 library and declaring typings that make NodeListOf extend Array :
That can be a workaround but it can't be official as a NodeList object is not an array. I'm also doing similar thing anyway.
for (let el of <Node[]><any>document.querySelectorAll("p")) {
}
PS: You can use document.queryAll
with the dom4 library and the return value will be real array.
Maybe in ES3/5 it's better to allow for-of on anything that has a .length
and a numeric index signature.
@JsonFreeman That will be convenient.
@JsonFreeman that would be extremely convenient for now, but would presumably mean that when target is switched to ES6 (hence emitting a real for... of
), the compiler would have to start rejecting code that previously compiled (and worked) when targeting ES5?
Right it's not backwards compatible with respect to upgrading to ES6. That's the tradeoff
Could work around that by falling back to for-loop generation in ES6 if the type is array-like but has no iterator symbol, but I guess that goes against the principle of TS not varying its code generation based on types. A pity because this would be an neat example of where you could leverage type information to be more helpful than a dynamic language!