Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For...of with HTMLCollection #5329

Closed
n2westman opened this issue Oct 19, 2015 · 22 comments
Closed

For...of with HTMLCollection #5329

n2westman opened this issue Oct 19, 2015 · 22 comments
Assignees
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue

Comments

@n2westman
Copy link

Hi,

Getting a compile error when trying to compile:

// ul is an HTMLElement
for (let child of ul.children) {
    //body
}

I get the following error: error TS2495: Type 'HTMLCollection' is not an array type or a string type.

Is there a way to get type support for this? Or is too much work to bother with?

@xLama
Copy link

xLama commented Oct 19, 2015

@n2westman
Copy link
Author

xLama, I am aware. However, the compiled code only needs an interface of .length, which means psuedoarrays should also be able to compile with the for..of syntax, right?

@xLama
Copy link

xLama commented Oct 19, 2015

I think If ECMAScript does not support HTMLCollection like an array, TypeScript neither.

However ECMAScript 6 supports it, so I am agree.

@n2westman
Copy link
Author

That's a good point!

@xLama
Copy link

xLama commented Oct 19, 2015

You can do this por the moment:

var foo:HTMLCollection;
var bar = [].slice.call(foo);
for (var g of bar){}

@n2westman
Copy link
Author

Yeah. The other thing you can do (if you promise not to mess with the body of the DOM in the loop) is:

for(let c of <any>bar) {}

@n2westman
Copy link
Author

Thanks! :)

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Oct 19, 2015
@saschanaz
Copy link
Contributor

ES6 does not support HTMLCollection on for-of loop as it is not iterable. NodeList is iterable and should be supported. Check #2695.

@xLama
Copy link

xLama commented Oct 20, 2015

@saschanaz What about this? #2696
for-of only works on arrays for ES3/ES5 by design.

@saschanaz
Copy link
Contributor

@xLama You are right. A limited number of iterable interfaces should be supported but currently not. #4947 is also related.

@xLama
Copy link

xLama commented Oct 20, 2015

@saschanaz There is a problem. How do you want to iterate them when emit to ES3/5 without complicate it?

@mhegazy mhegazy added the Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript label Dec 8, 2015
@mhegazy mhegazy added this to the TypeScript 1.8 milestone Dec 8, 2015
@mhegazy mhegazy modified the milestones: TypeScript 1.8, TypeScript 2.0 Jan 7, 2016
@zhengbli zhengbli assigned mhegazy and unassigned zhengbli Apr 21, 2016
@mhegazy mhegazy modified the milestones: TypeScript 2.1, TypeScript 2.0 Jun 6, 2016
@mhegazy mhegazy modified the milestones: TypeScript 2.1, Community Sep 21, 2016
@ghost
Copy link

ghost commented Mar 28, 2017

i think this is something that's missing from lib.dom.iterable.d.ts

i haven't tested other browsers but chrome and firefox both return a function (named values) for HTMLCollection.prototype[Symbol.iterator]

not that i know which one i should be reading but mdn provides some spec links for HTMLCollection

or is this something wrong with the spec? in "living standard" and "dom4" i can see NodeList has iterable<Node>; but HTMLCollection doesn't seem to have anything like that (is wanting to conveniently loop through an element's children really that uncommon?)

const myElement: Element = document.body;

const children: HTMLCollection = myElement.children;

// is this what i'm supposed to write?

for (const child of <IterableIterator<Element>> Array.prototype[Symbol.iterator].call(children)) {
	console.log(child);
}

// it's somehow even longer than the traditional ugly method

for (let i = 0; i < children.length; i++) { const child = children[i];
	console.log(child);
}

// this method is cheating but it also works:

interface HTMLCollection {
   [Symbol.iterator](): IterableIterator<Element>;
}

for (const child of children) {
	console.log(child);
}

@mhegazy
Copy link
Contributor

mhegazy commented Apr 19, 2017

Looking at this again, i believe the TS definitions do match the spec. NodeList is iterable, but HTMLCollection is not. and HTMLElement.children is an HTMLCollection see https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/children.

If the spec is wrong, then we need to change it, but i do not think i have enough DOM expertise to say which is correct.

@saschanaz
Copy link
Contributor

saschanaz commented Apr 19, 2017

WebIDL says:

If the interface has any of the following:

  • an iterable declaration
  • an indexed property getter and an integer-typed attribute named “length”
  • a maplike declaration
  • a setlike declaration

then a property must exist whose name is the @@iterator symbol, with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } and whose value is a function object.

Chromium on April 2016 implemented and merged the change based on this criteria.

This means we can add [Symbol.iterator] key, and also means that TSJS-lib-generator can automatically add the key but without methods e.g. values().

@saschanaz
Copy link
Contributor

microsoft/TypeScript-DOM-lib-generator#235 to fix this.

@felixfbecker
Copy link
Contributor

I see that PR was merged in May, but I still have this error with latest TS (2.4.2)

@RyanCavanaugh
Copy link
Member

@felixfbecker have you tried turning on --downlevelIteration?

@felixfbecker
Copy link
Contributor

felixfbecker commented Aug 15, 2017

No, didn't know that existed, but as I understand it I don't need it with target: ES6. Here's the error:

[ts] Type must have a '[Symbol.iterator]()' method that returns an iterator

when I jump to definition the typings don't have the Symbol.iterator defined. The flag doesn't help :/

@saschanaz
Copy link
Contributor

saschanaz commented Aug 16, 2017

The PR microsoft/TypeScript-DOM-lib-generator#235 added dom.es6.generated.d.ts but TS hasn't merged the file into the build process yet.

@tinganho
Copy link
Contributor

@kitsonk
Copy link
Contributor

kitsonk commented Sep 18, 2017

You need to compile with --downlevelIteration when targeting ES3/ES5, which is not supported in the playground at the moment.

@tinganho
Copy link
Contributor

Worked like a charm, thanks!

@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Nov 6, 2017
@mhegazy mhegazy modified the milestones: Community, TypeScript 2.7 Nov 6, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

9 participants