I have a Commune
interface generated by an OpenAPI generator:
/** Une commune du Code Officiel Géographique */
export interface Commune {
/** Code de la commune */
codeCommune: string;
/** Code du département */
codeDepartement: string;
/** Nom du département */
nomDepartement: string;
[...]
}
A CommunesComponent
gathers by a REST call some communes
: a Commune[]
array.
export class CommunesComponent implements OnInit {
/** Année du Code Officiel Géographique. */
@Input()
anneeCOG: number;
/** Locale du tri des communes */
@Input()
locale: string = 'fr_FR';
/** Liste des communes ordonnées par locale */
communes: Commune[];
/** Codes communes avec leur commune associée. */
communesMap: Map<string, Commune> = new Map<string, Commune>();
/** Code commune sélectionné. */
codeCommune: string = null;
/** Commune sélectionnée (objet). */
communeSelectionnee: Commune = null;
/** Libellé final de la commune sélectionnée. */
libelleCommuneSelectionnee: string;
[...]
/**
* Réaction à l'initialisation du composant :
* Lire les communes triées par locale, et sous forme de Map indexée par codeCommune.
*/
ngOnInit(): void {
// Vérification du paramètre d'appel (année)
if (this.anneeCOG < 2019 || this.anneeCOG >= 2100) {
const message = 'L\'année du code officiel géographique ' + this.anneeCOG + ' n\'est pas valide : choissez-là à partir de 2019.';
console.log(message);
return;
}
this.cogService.obtenirCommunesTriParLocale(this.anneeCOG, false, this.locale).subscribe(data => {
this.communes = data;
this.communes.forEach(commune => {
this.communesMap.set(commune.codeCommune, commune);
});
});
}
[...]
Where the service is called by one of these prototypes, also generated by OpenAPI:
public obtenirCommunesTriParLocale(anneeCOG: number, locale: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: '*/*'}): Observable<Array<Commune>>;
public obtenirCommunesTriParLocale(anneeCOG: number, locale: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: '*/*'}): Observable<HttpResponse<Array<Commune>>>;
public obtenirCommunesTriParLocale(anneeCOG: number, locale: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: '*/*'}): Observable<HttpEvent<Array<Commune>>>;
public obtenirCommunesTriParLocale(anneeCOG: number, locale: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: '*/*'}): Observable<any> {
[...]
}
And the data
it returns, if I put a breakpoint just at the forEach
to see its content, is:
Until now, I was using it in an *ngFor
, without troubles:
<datalist id="communesCOG">
<option *ngFor="let commune of communes" [value]="commune.codeCommune">{{commune.nomCommune}} ({{commune.nomDepartement}})</option>
</datalist>
Being in Angular 20 now, I'd like to put it in a @for
statement instead:
<datalist id="communesCOG">
@for (commune of communes; track commune.codeCommune) {
<option [value]="commune.codeCommune">{{commune.nomCommune}} ({{commune.nomDepartement}})</option>
}
</datalist>
But I'm receiving the error that Type Commune[] must have a [Symbol.iterator]() method that returns an iterator.
How can I put an iterator, and where, if it's what I have to do?
I don't understand why:
*ngFor="let commune of communes"
works@for (item of items ; track item.id)
applied to commune
and communes
doesn'tIf I say: *ngFor="let A of B"
and @for (C of D ; track C.id)
what are the types of A
, B
, C
and D
?
Is type A
≠ type C
or type B
≠ type D
?
or is it the @for
statement that doesn't work like *ngFor
?!
I think the problem is not a Typescript nor Angular error.
It has more to do with a false trigger from IntelliJ or Webstorm. You can try solving this by updating the Angular Language Service
to the latest version.
If the above does not help, then raise a ticket with webstorm or IntelliJ official support, for them to get back on why this false positive happens.
An alternative will be to try the alternative way to type an array. So instead of Commune[]
try Array<Commune>
which might solve your problem.