Error encountered with custom iterable in TypeScript when using the for...of loop

Attempting to create a custom iterable in my Angular application has resulted in an error message: "Type 'Connection' is not an array type or a string type." This occurs when trying to loop through the class using a for..of statement.

Further investigation revealed that this error can occur in ES5 when attempting to iterate through anything other than an array [] or a string using for..of. I believed that as TypeScript is a superset of ES6, which compiles down to ES5 as defined in tsconfig.json, I should be able to use this technique. Is my understanding incorrect?

Data Transfer Object (DTO):

export class Property{
key: string;
value: any;
}

Iterator:

import { Property } from './dto/property';

export class PropertyIterator {
data: Property[] = [];
index: number = 0;

constructor(object: Object) {
    Object.entries(object).forEach(
        ([key, value]) => {
            this.data.push({ key, value })
        }
    );
}

next() {

    var result = { value: undefined, done: false }
    if (this.index < this.data.length) {
        result.value = this.data[this.index++];
    } else {
        result.done = true;
        this.index = 0;
    }

    return result;
}

Iterable:

import { PropertyIterator } from './../../property-iterator';
import { ConnectionBuilder } from './connection-builder';
import { Property } from '../property';

export  class Connection implements Iterable<Property> {


    connectionId: number; //required
    type: string; //required
    username: string; //required
    password: string; //required
    path: string; //required

    serverName: string; //optional
    port: number; //optional

    constructor(builder: ConnectionBuilder){

        this.connectionId = builder.ConnectionId;
        this.type = builder.Type;
        this.username = builder.Username;
        this.password = builder.Password;
        this.path = builder.Path;
        this.serverName = builder.ServerName;
        this.port = builder.Port;   
    }

    [Symbol.iterator](){
        return new PropertyIterator(this);
    }

}

Usage example where the error occurs, with 'this.connection' being highlighted:

  getData(): Property[] {
let info: Property[] = []

for(let value of this.connection){
  info.push(value)
}

TypeScript Version: 2.7.2

Answer №1

Instead of relying on the array workaround, there is a more versatile solution available. Starting from version 2.3, TypeScript actually has built-in support for ES2015 iterators when targeting older versions like ES3/5. However, this feature is turned off by default. You can activate it by including the following line in your tsconfig.json file:

{
  "compilerOptions": {
    "downlevelIteration": true
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Customize the size of data points on your Angular 2 chart with variable

In my Angular 2 application, I am utilizing ng2-charts to create a line chart. The chart functions properly, showing a change in color when hovering over a point with the mouse. However, I want to replicate this behavior manually through code. Upon clicki ...

How can HostBinding be used to target a custom directive in order to deliver either a success or error message and show it on

I am incorporating a custom directive to display specific server messages/errors following an http request. For example, in the response or error section, I want to target the custom directive and present the emphasized message. The directive is already e ...

What is the reason behind Typescript's discomfort with utilizing a basic object as an interface containing exclusively optional properties?

Trying to create a mock for uirouter's StateService has been a bit challenging for me. This is what I have attempted: beforeEach(() => { stateService = jasmine.createSpyObj('StateService', ['go']) as StateService; } ... it(& ...

Tips for extracting certain keys from an interface using template string types?

I am dealing with a code snippet here that accepts a string array named possibleColumns for a specific database table. It then takes the incoming source and attempts to find a column containing {source}_id. For example, if the possibleColumns includes [&q ...

What could be causing my vis.js network's node hover popups to not function properly?

I've encountered an issue where, despite adding the 'title' property to my node objects, the pop up window with the title content doesn't appear when I hover over a node. Here are the options I've chosen and how I've set up m ...

Centering on request, Google Maps adjusts its view to focus on

When I select a row, I want to set the map center to the provided coordinates in Primeng. The issue is that while this.options works fine in ngOnInit, it doesn't work when called in the showCords() function. Below is my code: gmap.component.ts im ...

Right-align the text in the title of the material card

Why isn't the CSS aligning my title of matcard to the right? <mat-card [ngStyle]="{ 'margin':'5px','height':'130px'}"> <mat-card-header> <mat-card-title [ngStyle]="{ 'text-align': ...

Troubleshooting problems with angular 4 involving node-rdkafka, kafka-node, and loading

As someone new to web front-end development, I find myself a bit overwhelmed by the JS/Node/Angular world, especially when it comes to loading kafka client libraries. I've been exploring two options for accessing my kafka cluster: node-rdkafka and kaf ...

Which one should I prioritize learning first - AngularJS or Laravel?

As a novice web developer, I am embarking on my first journey into the world of frameworks. After much consideration, I have narrowed it down to two options: AngularJS and Laravel. Can you offer any advice on which one would be best for me to start with? ...

What is the best way to merge an array into a single object?

I have an array object structured like this. [ { "name": "name1", "type": "type1", "car": "car1", "speed": 1 }, { "name": &q ...

Placing images inside a div causes them to vanish

I encountered a strange issue where the images I added to a background disappeared. .Background1{ position:relative; top:0%; left:0%; height:100%; width:100%; content:url("/assets/backgroundlayer1.jpg") } .Background2{ posi ...

Can you point me in the right direction for declaring the ImageObject format in Angular?

To create an Image Slider similar to the one shown here, I need to load images from a source. However, I'm unsure about where exactly in the file (possibly in the component.ts?) I should declare them: imageObject: Array<object> = [{ ...

The Effect feature in Angular NgRx can sometimes lead to a never-ending loop

One thing I want to clarify is that I am still struggling to fully grasp the functionality of rxjs's operators. Despite studying them, when I use switchMap, mergeMap, or map in practice, the outcome appears to be the same. The code snippet below resu ...

Developing an asynchronous function to retrieve data from an external API utilizing Await/Async strategy

Currently, there is a method under development that retrieves a value from the API. What steps are needed to properly integrate Async/Await functionality into this process? fetchAccountById(){ let accountName; this.accountService.fetchDa ...

Use vertical gaps to separate items by applying the following technique:

One of my components is designed to act as a badge. The CSS for this component includes: https://i.sstatic.net/F0QZ6.png HTML: <div class="label label-as-badge"> {{ value.Termo }} <i class="fa fa-times"></i ...

How can we dynamically enable or disable a button based on the availability of input field data in an Angular FormGroup?

When it comes to deciding whether my form input field is required or not, I rely on the API data set. If the input is mandatory, I want to disable the button until the user inputs some value. As an absolute beginner in reactive form in angular, I could rea ...

Listening to events on the iterative variable of NgFor directive in Angular 2

Angular2 has been my latest exploration in solving a unique data binding challenge. In my UI, I've presented a javascript array of objects like a database recordset in an HTML table. Each row contains menus and inputs allowing users to modify the rec ...

What is the best way to prevent jest.mock from being hoisted and only use it in a single jest unit test?

My goal is to create a mock import that will be used only in one specific jest unit test, but I am encountering some challenges. Below is the mock that I want to be restricted to just one test: jest.mock("@components/components-chat-dialog", () ...

Utilizing a constant in setting the slotLabelFormat

I am attempting to configure the slotLabelFormat options in a React TypeScript project When I directly set slotLabelFormat={{ hour: "2-digit", minute: "2-digit", omitZeroMinute: false, meridiem: "short" }}, TypeScript compile ...

What is the best way to retrieve data (using GET) following React state changes?

Whenever a user clicks on one of the orderBy buttons (such as name/email/date), a new rendered result should be fetched from the server by sending a new get request. The same applies to page pagination. Simply setting this.setState({ [thestate]: [newState ...