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

Synchronization problem encountered in an Angular app involving playwright

Currently, I am working on automating a process where the service queries the database and displays the data on the user interface. However, the rendering takes a considerable amount of time, around 3 minutes. Despite using Playwright for automation, it do ...

Deactivating attribute inheritance / configuring component settings with script setup and Typescript

Is there a way to disable attribute inheritance for a component's options when using script setup syntax with Typescript in Vue 3? Here is the JavaScript code example: app.component('date-picker', { inheritAttrs: false, // [..] }) How ...

What is the correct way to invoke a function from an external JavaScript file using TypeScript?

We are currently experimenting with incorporating Typescript and Webpack into our existing AngularJS project. While I have managed to generate the webpack bundle, we are facing an issue at runtime where the program is unable to locate certain functions in ...

Tips for specifying types in protractor.conf.js while utilizing the @ts-check feature

Within my Angular CLI v7.3.6 project, there is a protractor.conf.js file that I'm looking to enhance with @ts-check in VSCode. When using @ts-check, I aim to execute the browser.getCapabilities() function in the onPrepare() callback but encountered an ...

Understanding the concept of inconsistent return points in Typescript: What implications does it carry?

I am currently working on converting a NodeJs JavaScript code to TypeScript. The code snippet below shows how I save uploaded files using JavaScript and now I'm encountering an error when trying to do the same in TypeScript. The error message says "Fu ...

Displaying data-table with only the values that are considered true

Right now, I am utilizing the AgReact table to exhibit data fetched from my endpoints. The data-table is functioning properly, however, it seems to be unable to display false values received from the endpoints on the table. Below are the snippets of my cod ...

Concatenate all sub-items within a JSON object

I have 2 Objects like this : [ { _id: ObjectId("62990f96345ef9001d9f2dfe"), deletedAt: null, expiredAt: ISODate("2022-06-05T19:29:26.746Z"), dataBarang: [ { vendor: ObjectId("6215dd91139c99003fe4c7cd ...

Faulty deduction can occur when implementing the return statement in an identity function, or when incorporating an optional parameter

Encountering strange behavior while working on identity functions in a wizard system schema. Using a constrained identity function for inference is causing issues with one property that cannot be inferred when using the following: When the return value fr ...

The custom validation in nestjs is throwing an error due to an undefined entity manager

I've been working on developing a custom validation for ensuring unique values in all tables, but I encountered this error: ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'getRepository') TypeError: Cannot read proper ...

How to Toggle Visibility of Angular2 Material Drop Down Menu?

My Code <mat-form-field class="button-spacing"> <mat-select placeholder="select" [(ngModel)]="dropDownOne"> <mat-option *ngFor="let first of test1" [value]="first"> {{ first }} </mat-option> </mat-select> </mat-fo ...

Encounter a problem while running `ng build` due to a module not

I was looking to automate the building of my Angular project on a separate CentOS 7 machine. Here are the versions being used: Angular CLI: 8.3.23 Node: 13.14.0 OS: linux x64 Angular: 8.2.14 ... animations, common, compiler, compiler-cli, core, forms ... ...

A guide to effectively converting and parsing a class object that includes Uint8Array elements

After stringifying a class object that contains a property in Uint8Array, and then parsing it later, the property is no longer in Uint8Array format. Here's an example: class Example { title:string; byteData:Uint8Array; ...

The React context hooks are failing to update all references

In my project, I am working on setting up a modal with a custom close callback. To achieve this, I used a useState hook to store the method and execute it within an already defined function called closeModal(). However, I encountered an issue when attempt ...

The functionality of the Drawer component in material-ui v1.0 seems to be incompatible with TypeScript

Every time I try to utilize Drawer from [email protected] using typescript, I encounter the following error: TS2322: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes & Re ...

Following the npm update, encountering errors with webpack

Upgrading the npm package to version 8.2.0 has caused issues in my React application. Here is a screenshot of the problem: https://i.stack.imgur.com/noQIz.png These are the error messages I see in the console: [HMR] Waiting for update signal from WDS.. ...

Having trouble incorporating a variable into the Discord Client object in Typescript

As a newcomer to Typescript, I am working on creating a Discord bot using Typescript. I am trying to add a variable called "commands" to the Client object. In JavaScript, you can achieve this using the following code: Javascript const { Client } = require ...

Stop users from switching to other tabs within mat-tab-group without using ViewChild

I am working with a mat-tab-group component in Angular : mat-tab-group class="brand-tabs" [disableRipple]="true" *ngSwitchCase="types.project" (selectedTabChange)="changeProjectTab($event)" [selectedIndex]="selectedProjectIndex" > . ...

Issue with Typescript Conditional Type not being functional in a function parameter

For a specific use-case, I am looking to conditionally add a key to an interface. In attempting to achieve this, I used the following code: key: a extends b ? keyValue : never However, this approach breaks when a is generic and also necessitates explicit ...

Using references to pass variables in TypeScript [Angular 8]

I have several variables within the html of this component that are assigned their values by the typescript file. The declaration in the html is as follows: <h1>{{myproperty1}}<\h1> <h1>{{myproperty2}}<\h1> <h1>{{myp ...

Can you explain the mechanics behind Angular Component CSS encapsulation?

Is it possible to avoid CSS conflicts when using multiple style sheets? Consider Style 1: .heading { color: green; } And Style 2: .heading { color: blue; } If these two styles are applied in different views and rendered on a layout as a Partial Vi ...