Tips for implementing dynamic properties in TypeScript modeling

Is there a way to avoid using ts-ignore when using object properties referenced as strings in TypeScript? For example, if I have something like:

const myList = ['aaa', 'bbb', 'ccc'];
const appContext = {};
for (let i=0; i<3; i++) {
  appContext[myList[i]] = 'newval' + i;
}

Even if I define my TypeScript type as:

interface IAppContext {
  aaa: string;
  bbb: string;
  ccc: string;

I still encounter TypeScript errors. How can this be handled correctly?

Answer №1

It would be greatly beneficial if the example code provided was a genuine minimum reproducible example showcasing the exact errors without any other mistakes or issues. However, I have an understanding of what may be occurring.

The primary issue that you are likely to encounter is the inference by the compiler that myList is of type string[]. This inference is reasonable on the part of the compiler because individuals often create arrays like const foo = ["a","b"] with the intention of modifying the values within the array later (e.g., foo.push("c")). A const declaration in this context only restricts reassignment (foo = ...) and does not prevent setting properties or invoking state-modifying methods on it.

To assist the compiler in cases where incorrect inference occurs on a literal value such as ["aaa","bbb","ccc"], one can utilize a const assertion. By asserting

const myList = ['aaa','bbb','ccc'] as const
, the compiler will assign the type readonly ["aaa", "bbb", "ccc"] to myList. This type represents a tuple of length 3 with immutable values that are string literals "aaa", "bbb", and "ccc" in sequential order.

Subsequently, your code should mostly compile smoothly by ensuring that appContext is asserted as an IAppContext, for instance,

const appContext = {} as IAppContext
. It's essential to understand that simply annotating it like
const appContext: IAppContext = {}
is inaccurate as it starts empty and is not a valid IAppContext. Through a type assertion, you reassure the compiler that although appContext initiates as an invalid IAppContext, it will eventually become one after execution. Yet, it remains your responsibility to ensure proper initialization. For instance, if myList were just ['aaa','bbb'], the code would compile without warnings, but issues might arise at runtime when calling appContext.ccc.toUpperCase().

In conclusion, below is the revised error-free code:

interface IAppContext {
    aaa: string;
    bbb: string
    ccc: string
}
const myList = ['aaa', 'bbb', 'ccc'] as const; // Constant context to retain literals
const appContext = {} as IAppContext; // Assertion due to initial emptiness
for (let i = 0; i < 3; i++) {
    appContext[myList[i]] = 'newval' + i
}

I hope this explanation proves helpful. Best of luck!

Playground link to code

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

Ways to retrieve the most recent update of a specialized typing software

When attempting to run typings install in a sample project with the below typings.js file, I received a warning. How can we determine the latest version number and what does the number after the + symbol signify? { "globalDependencies": { "core-js ...

Inheriting static attributes in Typescript without using the static keyword

My project involves utilizing multiple classes that represent entities from a database. abstract class Entity { static columns: Column[]; static showInNav: boolean; static dependencies: string[]; // non-static fields } class Entity_A exten ...

There is no link between the two containers

I am facing an issue where two containers need to connect with each other. However, when attempting to fetch data from one container, I encounter an ENOTFOUND error. Surprisingly, this code functions properly on my local system but fails within the contain ...

The browser is not displaying the HTML correctly for the Polymer Paper-Menu component

I attempted to implement a paper-menu, but I am facing issues with the rendered HTML and its interaction. When I click on a menu item, the entire list disappears due to the paper-item elements not being properly placed inside a key div within the paper-men ...

Find the identifier that does not currently exist in the collection of objects

There is a situation where I have an array and an object that consists of arrays of ids, which are essentially permission objects. My goal now is to extract the ids that do not exist in the given object. Can someone assist me with devising the necessary l ...

Guide on associating an array of object keys with an array of their corresponding values within a specified object

const obj = { wheels: 4, lights: 2, doors: 4 } customMapFunction(obj, { properties: ["wheels", "lights"], formatter: (wheels, lights) => `${wheels}-${lights}` // "4-2" }) How do I define the types for customMapFunction in TypeScript to ensure th ...

Guide to encapsulating a container within a map function using a condition in JSX and TypeScript

Currently, I am working with an array of objects that are being processed by a .map() function. Within this process, I have a specific condition in mind - if the index of the object is greater than 1, it should be enclosed within a div element with a parti ...

JavaScript: Employ array destructuring for improved code readability (eslintprefer-destructuring)

How can I resolve the ESLint error that says "Use array destructuring. eslint(prefer-destructuring)"? The error occurs on this line of my code: let foo = 1; foo = obj.data[i][1]; //ESLint error on this line If anyone could provide assistance in fixing thi ...

Fixing ngModel and click functionality issues in dynamic HTML content within Angular 4

I am struggling to insert HTML content into a specific id by using Angular. Although the HTML displays, the functionality of ngModel and click event is not working. How do I resolve this issue? app.component.html <div id="myid"> </div> app. ...

Guide on validating a dropdown using template-driven forms in Angular 7

Having trouble validating a dropdown select box, possibly due to a CSS issue. Any suggestions on how to fix this validation problem? Check out the demo here: https://stackblitz.com/edit/angular-7-template-driven-form-validation-qxecdm?file=app%2Fapp.compo ...

Utilizing HTML imports in Typescript for efficient use as TemplateStringLiteral

Recently, I started using TypeScript for the first time and I'm looking to integrate it into my webpack build. Currently, I am working with ts-loader and babel-loader to load TypeScript files while also attempting to include HTML files within the scr ...

Struggled with setting up the WebSocket structure in typescript

Issue Running the code below results in an error: index.tsx import WebSocket from 'ws'; export default function Home() { const socket = new WebSocket('ws://localhost:1919/ws'); return ( <div>Home</div> ); } ...

Angular File Upload Button Tutorial

English is not my first language, so please excuse any mistakes. I recently started learning Angular and I'm attempting to build a file upload button that lets users upload files based on dropdown menu options (such as USA States). Once uploaded, the ...

"Encountering issues with Firebase deployment related to function-builder and handle-builder while working with TypeScript

I encountered 4 errors while executing firebase deploy with firebase cloud functions. The errors are originating from files that I didn't modify. node_modules/firebase-functions/lib/function-builder.d.ts:64:136 - error TS2707: Generic type 'Req ...

What is the best way to ensure every component in Angular 2 has access to a custom pipe?

I've come up with a unique idea to create a custom rainbowize pipe that wraps each letter in a span with a random color of the rainbow as the css color property. My goal is to implement this custom pipe across all components in my app without having t ...

What are the steps to incorporate SignalR into a TypeScript project?

Working on an asp.net mvc 4.5 project with typescript in the client side, I successfully installed and configured signalR on the server side. To integrate it into my project, I also installed signalr.TypeScript.DefinitelyTyped with jquery. In my typescrip ...

Oops! The API request was denied with error code 401 - Unauthorized in React

I have been working on incorporating an API into my front-end project using React/Typescript. The documentation for the API specifies that authorization requires a key named token with a corresponding value, which should be included in the header. To stor ...

Create a custom component that wraps the Material-UI TextField component and includes default

I have been exploring React and had a question regarding wrapping a component like TextField from mui to add new props along with the existing ones. I attempted to do this but am struggling to figure out how to access the other props. Can anyone help me ...

What is the method for retrieving the second type of property from an array of objects?

I have a collection of objects that map other objects with unique identifiers (id) and names (name). My goal is to retrieve the name corresponding to a specific id. Here is my initial approach: const obj = { foo: { id: 1, name: 'one' }, ...

Typescript: The dilemma of losing the reference to 'this'

My objective is to set a value for myImage, but the js target file does not contain myImage which leads to an error. How can I maintain the scope of this within typescript classes? I want to load an image with the Jimp library and then have a reference to ...