Specify the object key type when using a `for-in` loop

My current situation involves an object type:

interface ShortUrlParam {
    openid: string;
    avatar: string;
    nickname: string;
}

const param: ShortUrlParam = {
    openid: 'abc123',
    avatar: '',
    nickname: 'wenzi'
}

let query = '';
for(let key in param) {
    query += `&${key}=${encodeURIComponent(param[key])}`; // encountering an error here
}

When accessing param[key], I receive the following error message:

'Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ShortUrlParam'. No index signature with a parameter of type 'string' was found on type 'ShortUrlParam'.ts(7053)

I have come up with two potential solutions, both not without flaws.

1. Redefining the interface ShortUrlParam

interface ShortUrlParam {
    openid: string;
    avatar: string;
    nickname: string;
    [key: string]: string;
}

2. Treating param as any

for(let key in param) {
    query += `&${key}=${encodeURIComponent((param as any)[key])}`;
}

My inquiry is whether there exists a more optimal solution to this issue?

Answer №1

Typescript does not allow type annotations for variables declared in a for..in loop due to the open nature of object types. This means that an object can have additional properties beyond what is expected, making it impossible to narrow down the type of a variable introduced in a loop.

However, there are workarounds available. One option is to declare the variable outside the loop with the desired type annotation:

let key: keyof ShortUrlParam;
for (key in param) {
  query += `&${key}=${encodeURIComponent(param[key])}`;
}

This approach ensures type safety, although caution should be taken if unexpected properties are added to the object later on.


An alternative method is to assert the type of the variable within the loop using type assertions:

for (let key in param) {
  query += `&${key}=${encodeURIComponent(param[key as keyof ShortUrlParam])}`;
}

Both approaches are more secure than using 'any', as they help catch errors where extra properties are added to the object. Hopefully, these suggestions prove helpful. Good luck!

Answer №2

Not quite as secure as jcalz's solution, but still handy for type hints when you don't have a specific type definition readily available (maybe because you didn't define an object literal right before). You can make an educated guess instead of resorting to any. Just stay away from any...

Furthermore, the JavaScript heap within a for loop gets reset after each iteration, so using const instead of let ensures that the key remains unchanged. If you do need to change the key being iterated over, stick with a traditional for-loop to keep your code clean.

Here is a general example:

for (const key in thing) {
  doThings(key as keyof typeof thing)
}

And here's an example relevant to your query:

for (const key in param) {
  query += `&${key}=${encodeURIComponent(param[key as keyof typeof param])}`
}

Answer №3

Attempt this:

for(let index=0;index<parameters.length; index++) {
  let keyValue = parameters[index];
  searchQuery += `&${keyValue}=${encodeURIComponent((parameters as any)[keyValue])}`;
}

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

What is the best way to click on a particular button without activating every button on the page?

Struggling to create buttons labeled Add and Remove, as all the other buttons get triggered when I click on one. Here's the code snippet in question: function MyFruits() { const fruitsArray = [ 'banana', 'banana', & ...

Combining types with additional features

Is it possible to configure the TypeScript compiler to generate an error when a function is called with an argument that can belong to both cases in a union type? For example: interface Name { name: string } interface Email { email: string } type ...

Moving SVG Module

My goal is to create a custom component that can dynamically load and display the content of an SVG file in its template. So far, I have attempted the following approach: icon.component.ts ... @Component({ selector: 'app-icon', templa ...

Is there an automatic bottom padding feature?

Currently, I am facing a challenge in fitting the loader into the container without it being overridden by the browser. Using padding-bottom is not an ideal solution as it results in the loader appearing un-resized and unprofessional. Any suggestions or co ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...

Tips for utilizing the 'crypto' module within Angular2?

After running the command for module installation: npm install --save crypto I attempted to import it into my component like this: import { createHmac } from "crypto"; However, I encountered the following error: ERROR in -------------- (4,28): Canno ...

Struggling to grasp how to implement Redux and React-router together in one component

I have recently embarked on learning TypeScript and encountered a confusing behavior. Upon encountering this error: Type 'ComponentClass<{}>' is not assignable to type 'StatelessComponent<void | RouteComponentProps<any>> ...

Angular routing is failing to redirect properly

After creating a sample Angular app, the goal is to be redirected to another page using the browser URL http://localhost:1800/demo. The index.html file looks like this: <!doctype html> <html lang="en"> <head> <title>Sample Ang ...

Issue with React hook forms and shadcn/ui element's forwardRef functionality

Greetings! I am currently in the process of creating a form using react-hook-form along with the help of shadcn combobox. In this setup, there are two essential files that play crucial roles. category-form.tsx combobox.tsx (This file is utilized within ...

Switch the checkbox attribute for multiple items within a carousel using Angular 2/Typescript

I am currently working on a carousel feature where each item has a checkbox above it. My goal is to be able to click on an item and have its corresponding checkbox checked. The current code successfully achieves this, but the issue I'm facing is that ...

The TypeScript inference feature is not functioning correctly

Consider the following definitions- I am confused why TypeScript fails to infer the types correctly. If you have a solution, please share! Important Notes: * Ensure that the "Strict Null Check" option is enabled. * The code includes c ...

Steps for resolving the problem of the Express error handler not being executed

This question has come up again, and I have searched for solutions but none seem to work. Your assistance in debugging the issue would be greatly appreciated. I have a separate errorHandler set up as middleware. In my error-handler.ts file: import expres ...

An unconventional approach to conducting runtime checks on Typescript objects

I've been working on a server application that receives input data in the form of JavaScript objects. My main task is to validate whether these data meet certain requirements, such as: having all required fields specified by an interface ensuring th ...

Issue encountered while generating a dynamic listing using Angular

My goal is to generate a dynamic table using Angular. The idea is to create a function where the user inputs the number of rows and columns, and based on those values, a table will be created with the specified rows and columns. However, I am facing an iss ...

Messages are not being emitted from the socket

I've been encountering an issue with message transmission from client to server while using React and ExpressJS. When I trigger the sendMessage function on the client side, my intention is to send a message to the server. However, for some reason, the ...

Is it possible to extract specific columns from the Convex database?

I am looking to retrieve all columns from a table using the following code snippet. Is there a more efficient way to achieve this? I couldn't find any information in the documentation. Does anyone have a workaround or solution? const documents = await ...

Various dateInput formats supported by mat-datepicker

I'm facing an issue while configuring two mat-datepickers with different date formats - "MM/YYYY" and "DD/MM/YYYY". I attempted to set the format for MM/YYYY in one module and the format for DD/MM/YYYY in the app module. Here is my first code snippet ...

The attribute 'status' is not found in the 'ServerResponse' type (TS2339)

I've attempted to develop an interface and install React types, but the only way it seems to work is when I write the code in JavaScript. However, within a TypeScript project, I encounter this error: Property 'status' does not exist on typ ...

When should I schedule the execution of the .spec and .po.ts files in Protractor?

Curious about TypeScript and Protractor: I have a couple of basic helper functions stored in a shared.po.ts file within my Protractor suite. These functions are triggered by the third it() in my .spec file - meaning they are not immediately called upon ru ...

Learn how to utilize React lazy effectively in components that utilize Redux compose without any similarities to type 'IntrinsicAttributes'

Here is the structure of a component that is exported with compose from redux. This component is called TestInspector.tsx export interface TestInspectorProps { closeInspector: () => void; onExpand: () => void; isFullScreen: boolean; selected ...