Alter the attributes of an instance in a class using a function

Attempting to explain a simple method in TypeScript.

This method should allow modification of data for any object type within the data attribute. In simpler terms, we can modify, add, or remove data based on the specified data type, and TypeScript facilitates this by establishing clear associations with each type. For instance, if the value to be modified is a number, the system only allows entry of numerical values. (I hope that's clear).

Here's an easy-to-understand example:

interface BackgroundProperties {
    backgroundColor: string;
    paddingTop: number;
    paddingBottom: number;
    paddingLeft: number;
    paddingRight: number;
    hasShadow: boolean;
    shadowBlur: number;
    shadowColor: string;
    shadowOffsetX: number;
    shadowOffsetY: number;
}

const o = new Obj();
o.setBackgroundProperty("backgroundColor", "#000"); // Needs to be a string
o.setBackgroundProperty("backgroundColor", 0); // Error received
o.setBackgroundProperty("paddingBottom", 10); // Should be a number
o.setBackgroundProperty("paddingBottom", "10"); // Error encountered

At present, my code looks like this:

interface BackgroundProperties {
    backgroundColor: string;
    paddingTop: number;
    paddingBottom: number;
    paddingLeft: number;
    paddingRight: number;
    hasShadow: boolean;
    shadowBlur: number;
    shadowColor: string;
    shadowOffsetX: number;
    shadowOffsetY: number;
}

class Obj {
  data: { background: BackgroundProperties };

  constructor() {
    this.data = {
     background: {
          backgroundColor: "#ABB8C3",

          hasShadow: true,
          shadowColor: "rgba(0,0,0,0.55)",
          shadowBlur: 68,
          shadowOffsetY: 12,
          shadowOffsetX: 0,

          paddingBottom: 56,
          paddingTop: 56,
          paddingLeft: 56,
          paddingRight: 56
      }
    }
  }

  public setBackgroundProperty<O extends BackgroundProperties, K extends keyof O>(key: K, value: O[K]) {
        if (String(key).endsWith('Color') && typeof value === 'string' ? value : '')
            throw new Error(`The ${key.toString()} background color value is not a hexadecimal color!`);
        
        this.data.background[key] = value;
        return this;
  }
}

However, I encounter an error on this line:

this.data.background[key] = value;
. The error message states:

Type 'K' cannot be used to index type 'BackgroundProperties'.

I've searched for solutions online but have been unable to identify the root cause.

Here's a replicated example on TypeScript Playground.

Answer №1

When you specify that O extends BackgroundProperties, it does not ensure that K is a valid key of BackgroundProperties itself. It might be a key of the extended type. However, data.background is specifically of the type BackgroundProperties, and can only accept keys from that type.

To resolve this issue, you could modify the signature as follows:

public setBackgroundProperty<K extends keyof BackgroundProperties>(key: K, value: BackgroundProperties[K]) {

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

Issue: Angular 7 unable to route directly to URL with specific ID

When I click on the navigation link with code for button click, it works perfectly fine: this.router.navigate(['/dashboard', this.selectedDateString]); However, if I manually type the URL into the address bar like this: I receive a forbidden! ...

The deployment of the remix is unsuccessful in Vercel, even though it functions perfectly during development. The error message states that 'AbortController' is not

I'm new to React and could use some assistance with a deployment issue on Vercel. Any ideas on why this is failing? I haven't explicitly used AbortController anywhere, so I'm suspecting it might be related to one of the installed packages? ...

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 ...

Constructing hierarchical objects in JavaScript

I am looking to create a complex nested object in JavaScript that follows a specific structure. const data = { name: 'Context 1', children: [ { name: 'Option 1', children: [ { name: 'Context&ap ...

Can an element on a webpage be dynamically assigned an ID using JavaScript or PHP?

Is it possible to dynamically set the ID of an element during runtime of a webpage? Let's consider this scenario - <body id="body1"> Now, I would like to dynamically set the ID of this "body" element using a variable value in PHP code. Is som ...

Can one validate a single route parameter on its own?

Imagine a scenario where the route is structured as follows: companies/{companyId}/departments/{departmentId}/employees How can we validate each of the resource ids (companyId, departmentId) separately? I attempted the following approach, but unfortunate ...

Can an integer-like object with the ability to store instance variables be created in Python?

Can Python support a custom data object that acts like a typical integer during math operations and comparisons while also having the ability to hold instance variables? In essence, it should allow for the following functionality: pseudo_integer = Pseudo ...

Exploring the Power of Modules in NestJS

Having trouble with this error - anyone know why? [Nest] 556 - 2020-06-10 18:52:55 [ExceptionHandler] Nest can't resolve dependencies of the JwtService (?). Check that JWT_MODULE_OPTIONS at index [0] is available in the JwtModule context. Possib ...

WebStorm disregards tsconfig compiler directives when working with Angular applications

My project structure was created using angular-cli, which includes a root tsconfig.json, src/tsconfig.app.json, and src/tsconfig.spec.json. Despite having the noImplicitAny and strict options enabled in the root configuration, I do not receive error notifi ...

Encountering an error when attempting to access an object property dynamically by using a passed down prop as a variable in Vue 2 & Vuex

I have been struggling for hours to find a solution to this problem, but so far I've had no luck. I've looked at these two questions, but they didn't provide the answers I needed: Dynamically access object property using variable Dynamical ...

Capture and handle JavaScript errors within iframes specified with the srcDoc attribute

My current project involves creating a React component that can render any HTML/JavaScript content within an iframe using the srcDoc attribute. The challenge I am facing is implementing an error handling system to display a message instead of the iframe ...

Utilizing JavaScript variables imported from an external library in Next.js: A Guide

I am currently working on a Next.js with Typescript website and I am in the process of adding advertisements. The ad provider has given me instructions to embed this JavaScript code on my site: <script src="//m.servedby-buysellads.com/monetization. ...

Challenge encountered with asynchronous angular queries

Dealing with asynchronous calls in Angular can be tricky. One common issue is getting an array as undefined due to the asynchronous nature of the calls. How can this be solved? private fetchData(id){ var array = []; this.httpClient.get('someUrl ...

Encountering a problem with the mock object in Angular 11 unit testing when converting a JSON object to a TypeScript interface

Within my Angular 11 application, I am working with a JSON response and have defined an interface to match the structure of this JSON object. The JSON object looks like this: { "division": { "uid": "f5a10d90-60d6-4937-b917- ...

The Angular 2 router is not compatible with using the same component but with different IDs

Currently utilizing the alpha8 router with 3 main routes: export const appRoutes: RouterConfig = [ { path: '', component: LandingComponent }, { path: 'blog', component: BlogComponent }, { path: 'posts/:id', compon ...

Monitoring changes within the browser width with Angular 2 to automatically refresh the model

One of the challenges I faced in my Angular 2 application was implementing responsive design by adjusting styles based on browser window width. Below is a snippet of SCSS code showing how I achieved this: .content{ /*styles for narrow screens*/ @m ...

Encountered an error with Aurelia webpack 4 when trying to load a necessary CSS file during runtime

I encountered a unique issue with webpack and aurelia that I can't seem to figure out. After creating a new webpack configuration based on online resources and official documentation, the compilation goes smoothly without any errors. However, during r ...

The object's type remains a mystery

While working on implementing jwt authentication in Ionic, React with TypeScript, I faced a typescript error when trying to add a check in my App.tsx file after successful implementation. The error stated: Object is of type 'unknown' Below is ...

Utilizing a variable name as an object key in TypeScript

Can this be achieved? static readonly statusMapping: { [key in UploadStatus]: PopupMessageStatus } = { UploadStatus.COMPLETED : PopupMessageStatus.COMPLETED } UploadStatus is an enum with numeric values, where UploadStatus.COMPLETED = 0 p ...

Issue: Troubleshooting data serialization process using getStaticProps in Next.js

I attempted to retrieve data from an API, but unfortunately encountered the following error: Server Error Error: Issue with serializing .results returned from getServerSideProps in "/". Reason: JSON serialization does not support undefin ...