Guide to Declaring and Unpacking a Tuple Array within a for..of Loop in TypeScript

In a test file, I have the JavaScript code shown below:

for (let [input, expected] of [
  ['<h1>test</h1>', ['</h1>']],
  ['<h1><b>test</b></h1>', ['</h1>', '</b>']],
  ['<h1><b>test</b> lol</h1>', ['</h1>']],
]) {
  const result = functionToTest(input);
  for (let i in expected) {
    if (result[i] !== expected[i]) {
      throw Error("test failed")
    }
  }
}

However, TypeScript does not accept this code because functionToTest expects a string, and TypeScript believes that input has type string | string[].

An alternate approach is to store the test data in a separate variable with declared type as a list of tuples:

const testData: [string, string[]][] = [
  ['<h1>test</h1>', ['</h1>']],
  ['<h1><b>test</b></h1>', ['</h1>', '</b>']],
  ['<h1><b>test</b> lol</h1>', ['</h1>']],
]

for (let [input, expected] of testData) {
  const result = listClosingTagsAtEnd(input);
  for (let i in expected) {
    if (result[i] !== expected[i]) {
      throw Error("test failed")
    }
  }
}

Despite this solution, I prefer not having to create an additional variable to hold data that is only used once. It was more convenient when the data was declared directly in the for loop.

I attempted to define types within the for loop using

let [input, expected]: [string, string[]] of
, but encountered the error
The left-hand side of a 'for...of' statement cannot use a type annotation.
.

Additionally, adding : [string, string[]] after declaring test data in the for loop resulted in TypeScript identifying it as a JavaScript label.

Is there a way to correctly specify destructuring types while keeping the declaration of test data inside the for loop?

Answer №1

I managed to solve this issue on my own through trial and error, so I thought it would be helpful to share the solution on Stack Overflow in case others are facing a similar problem. Here is the step-by-step guide:

for (let [input, expected] of <[string, string[]][]>[
  //                          ^--------------------^
  //                             type declaration
  ['<h1>test</h1>', ['</h1>']],
  ['<h1><b>test</b></h1>', ['</h1>', '</b>']],
  ['<h1><b>test</b> lol</h1>', ['</h1>']],
]) {
  const result = functionToTest(input);
  for (let i in expected) {
    if (result[i] !== expected[i]) {
      throw Error("test failed")
    }
  }
}

Edit: I came across another solution in this stack overflow answer! By simply adding as const after the literal:

for (let [input, expected] of [
  ['<h1>test</h1>', ['</h1>']],
  ['<h1><b>test</b></h1>', ['</h1>', '</b>']],
  ['<h1><b>test</b> lol</h1>', ['</h1>']],
] as const) {
//   ^---^
//    HERE
  const result = functionToTest(input);
  for (let i in expected) {
    if (result[i] !== expected[i]) {
      throw Error("test failed")
    }
  }
}

This approach allows TypeScript to determine that input has a type of

"<h1>test</h1>" | "<h1><b>test</b></h1>" | "<h1><b>test</b> lol</h1>"
, providing the most accurate description of its type.

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

Choosing custom element children once they're connected to the DOM: A guide

My goal is to retrieve the value of transaction-name__inputbox when the user clicks on the transaction-add__button. The function transactionAddHandler is triggered upon clicking the button. However, my attempt to select this element using document.querySe ...

The module "install-npm-version" could not be located

I am currently working on a project using TypeScript, which you can find at this GitHub repository. However, when I attempt to use the package in another project, I encounter an error that says Cannot find module 'install-npm-version'. Steps to ...

When transmitting information to the server, the browser initiates four requests

I am encountering an issue with my React component. The problem arises when I try to retrieve the current geographic coordinates, as they are being fetched 4 times consecutively. This same glitch occurs when attempting to send the coordinates to the serv ...

Ensuring Type Compatibility Between Classes and Object Literals in TypeScript

When working with TypeScript, it is important to note that an object literal can be assigned to a class typed variable as long as the object provides all properties and methods required by the class. class MyClass { a: number; b: string; } // The co ...

applying multiple angular filters on table column values

I'm currently facing a challenge with implementing a filter pipe that can handle multiple values across multiple attributes in a table. While I have successfully managed to filter multiple values on a single attribute, I am struggling to achieve the ...

Angular 7 TypeScript code not updating value

UPDATE: I'm having trouble with my code not updating the selected value with the new one entered in the input field "newVb". The error message says 'this.newVarde' is undefined when it reaches the line 'this.selectedVarde = this.newVard ...

Tips for updating a selected value without altering the reference value

Encountering an issue with the angular framework when trying to select a value from ng-for loop <tr *ngFor="let dept of department" (click)="clinicChoose(dept)"> <td class="text-center">{{dept.sectionCode}}</t ...

Could you provide insight into the reason behind debounce being used for this specific binding?

function debounce(fn, delay) { var timer return function () { var context = this var args = arguments clearTimeout(timer) timer = setTimeout(function () { fn.apply(context, args) }, delay) ...

Steps for setting up Protractor Cucumber Report with TypeScript and screenshots:

I've searched for many tutorials on setting up Protractor with Cucumber reports and screenshots in TypeScript, but have had no luck. Can you provide assistance in configuring this? ...

Ways to display a component with different initial state when needed?

Within my application, I have a specific component that independently manages its state using the useState hook. However, I am encountering an issue where I need to conditionally render multiple instances of this same component: const PaymentScannerView: R ...

Dealing with Angular 2: Issues with Observables failing to return nested objects from services

I have an angular service that handles the retrieval of user objects. These user objects contain various attributes along with an array of walls. The service returns an observable to the component that calls it. While I am able to successfully create a u ...

Determine whether something has the potential to be a string in TypeScript

I am looking to create a TypeScript type that can identify whether an element has the potential to be a string. This means the element should have the type "string" or "any", but not "number", "boolean", "number[]", "Person", etc. I have experimented wit ...

Encountered an error: Object(...) function not defined when using React, Formik, and Webpack

I have encountered an issue while trying to use both Formik and React-Form-Hooks in my project. Despite using Typescript as my language and Babel as the transpiler, both libraries throw the same error when compiled. Uncaught TypeError: Object(...) is not ...

Error message stating: "Form control with the name does not have a value accessor in Angular's reactive forms."

I have a specific input setup in the following way: <form [formGroup]="loginForm""> <ion-input [formControlName]="'email'"></ion-input> In my component, I've defined the form as: this.log ...

When selecting a different file after initially choosing one, the Javascript file upload event will return e.target as null

Currently, I have implemented file uploading using <input>. However, when attempting to change the file after already selecting one, the website crashes and states that event.target is null. <Button label="Upload S3 File"> <input ...

Can an L1 VPC (CfnVpc) be transformed into an L2 VPC (IVpc)?

Due to the significant limitations of the Vpc construct, our team had to make a switch in our code to utilize CfnVpc in order to avoid having to dismantle the VPC every time we add or remove subnets. This transition has brought about various challenges... ...

An issue occurred at line 2, character 16 in the generateReport.service.ts file: TypeScript error TS2580 - The term 'require' is not recognized

I have a requirement in my app to generate a report in the form of a Word document with just a click of a button. Previously, I successfully accomplished this using the "officeGen" module in a separate project. You can find more information about the modul ...

Instance of exported class declared in Typescript

Currently, I am in the process of developing my initial declaration file for a foreign library known as react-native-background-timer. Within this library, there exists a default export that I am uncertain about how to declare within the index.d.ts file. ...

Webpack: Creating a shared global variable accessible across non-module scripts

I am facing a challenge with integrating Typescript UMD modules into legacy code that does not follow any module pattern. My hope was to find a Webpack loader or plugin that could generate global variables for specific modules instead of treating them as ...

Exploring the contrast of && and ?? in JavaScript

My current focus is on utilizing the Logical AND && and Nullish coalescing operator ?? in handling conditional rendering of variables and values. However, I find myself struggling to fully comprehend how these operators function. I am seeking clar ...