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

QueryList is not iterable #29842

Closed
calebegg opened this issue Apr 11, 2019 · 7 comments

Comments

@calebegg
Copy link
Member

@calebegg calebegg commented Apr 11, 2019

Docs say

Implements an iterable interface, therefore it can be used in both ES6 javascript for (var i of items) loops as well as in Angular templates with *ngFor="let i of myList".

This is plainly untrue:

https://github.com/angular/angular/blob/master/packages/core/src/linker/query_list.ts

In TS, I get:

TS2488: Type 'QueryList' must have a 'Symbol.iterator' method that returns an iterator.

even though we use --downlevelIteration

@ngbot ngbot bot added this to the needsTriage milestone Apr 11, 2019
@pkozlowski-opensource

This comment has been minimized.

Copy link
Member

@pkozlowski-opensource pkozlowski-opensource commented Apr 11, 2019

For the reference: #17414, #7022, #5437 and probably many others...

@trotyl

This comment has been minimized.

Copy link
Contributor

@trotyl trotyl commented Apr 13, 2019

@pkozlowski-opensource

I don't think there is a way to make TS happy when targeting ES5 (not all browser Angular supports support ES2015 - more specifically Symbol here)

The previous reply doesn't make sense any more, Symbol is a required polyfill in Angular CLI when targeting es5, so there is no issue for supporting Symbol.iterator.

@piotrtomiak

This comment has been minimized.

Copy link
Contributor

@piotrtomiak piotrtomiak commented May 13, 2019

This issue is also hurting users in WebStorm with *ngFor syntax: https://youtrack.jetbrains.com/issue/WEB-38825 . QueryList is not assignable to NgIterable. I think NgIterable could be defined in a more forgiving way to accept QueryList.

@cexbrayat

This comment has been minimized.

Copy link
Contributor

@cexbrayat cexbrayat commented May 19, 2019

This also affects Ivy users with fullTemplateTypeCheck on (8.0.0-rc.4).
A component like:

@Component({
  selector: 'ns-tabs',
  template: `
  <ul class="nav nav-tabs">
    <li class="nav-item" *ngFor="let tab of tabs">
      <a class="nav-link">{{ tab.title }}</a>
    </li>
  </ul>`
})
export class TabsComponent {
  @ContentChildren(TabDirective) tabs: QueryList<TabDirective>;
}

throws:

__ng_typecheck__.ts:162:24 - error TS2322: Type 'QueryList<TabDirective>' is not assignable to type 'NgIterable<any>'.
  Type 'QueryList<TabDirective>' is missing the following properties from type 'any[]': pop, push, concat, join, and 18 more.

162     var _t2 = _ctor1({ ngForOf: ctx.tabs });

It can be fixed by adding .toArray() but it would be better to fix the underlying issue.

@Splaktar

This comment has been minimized.

Copy link
Member

@Splaktar Splaktar commented Oct 15, 2019

We've seen this issue in the Components repo as well. It would be nice to fix the typing to support QueryList in ngForOf.

@cexbrayat

This comment has been minimized.

Copy link
Contributor

@cexbrayat cexbrayat commented Nov 1, 2019

Update: since the latest v9 releases (9.0.0-rc.0 at the time of writing), you can enable fullTemplateTypeCheck without encountering this issue.

A stricter option, strictTemplates, has been introduced, and the issue is now encountered only with this option activated.

alxhub added a commit to alxhub/angular that referenced this issue Nov 1, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
alxhub added a commit to alxhub/angular that referenced this issue Nov 1, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
alxhub added a commit to alxhub/angular that referenced this issue Nov 1, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
alxhub added a commit to alxhub/angular that referenced this issue Nov 18, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
alxhub added a commit to alxhub/angular that referenced this issue Nov 18, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
alxhub added a commit to alxhub/angular that referenced this issue Nov 18, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes angular#29842
@alxhub alxhub closed this in bb290ce Nov 19, 2019
alxhub added a commit that referenced this issue Nov 19, 2019
Originally, QueryList implemented Iterable and provided a Symbol.iterator
on its prototype. This caused issues with tree-shaking, so QueryList was
refactored and the Symbol.iterator added in its constructor instead. As
part of this change, QueryList no longer implemented Iterable directly.

Unfortunately, this meant that QueryList was no longer assignable to
Iterable or, consequently, NgIterable. NgIterable is used for NgFor's input,
so this meant that QueryList was not usable (in a type sense) for NgFor
iteration. View Engine's template type checking would not catch this, but
Ivy's did.

As a fix, this commit adds the declaration (but not the implementation) of
the Symbol.iterator function back to QueryList. This has no runtime effect,
so it doesn't affect tree-shaking of QueryList, but it ensures that
QueryList is assignable to NgIterable and thus usable with NgFor.

Fixes #29842

PR Close #33536
@dhiegoatencio

This comment has been minimized.

Copy link

@dhiegoatencio dhiegoatencio commented Dec 2, 2019

This also affects Ivy users with fullTemplateTypeCheck on (8.0.0-rc.4).
A component like:

@Component({
  selector: 'ns-tabs',
  template: `
  <ul class="nav nav-tabs">
    <li class="nav-item" *ngFor="let tab of tabs">
      <a class="nav-link">{{ tab.title }}</a>
    </li>
  </ul>`
})
export class TabsComponent {
  @ContentChildren(TabDirective) tabs: QueryList<TabDirective>;
}

throws:

__ng_typecheck__.ts:162:24 - error TS2322: Type 'QueryList<TabDirective>' is not assignable to type 'NgIterable<any>'.
  Type 'QueryList<TabDirective>' is missing the following properties from type 'any[]': pop, push, concat, join, and 18 more.

162     var _t2 = _ctor1({ ngForOf: ctx.tabs });

It can be fixed by adding .toArray() but it would be better to fix the underlying issue.

using .toArray() in ngFor fixed the problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants
You can’t perform that action at this time.