• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

224
Views
Update dynamic key in class in Typescript

I have a class, for example:

class Team {
  pointsFor: number;
  pointsAgainst: number;
  
  constructor(){
    this.pointsFor = 0;
    this.pointsAgainst = 0;
  }
}

Now I would like to make a method for this class where I can update the property by key for example:

updateStats = (bool: boolean, property: string, increment: number) =>{
  const key: keyof this = bool ? `${property}For` : `${property}Against`
  this[key] += increment
}

However I get an error that string is not assignable to keyof this, and if I force the type like

const key: keyof this = bool ? `${property}For` as keyof this : `${property}Against` as keyof this

then I get an error: "Operator '+=' cannot be applied to types 'this[keyof this]' and 'number'."

Is there a way to accomplish what I want here where I call team.updateStats(true, 'points', 2) and update pointsFor?

about 3 years ago · Juan Pablo Isaza
2 answers
Answer question

0

I really wouldn't recommend using string manipulation with TypeScript class properties the way you are trying to.

By using keyof this, you are essentially referring to all the keys of the class, like pointsFor: number, pointsAgainst: number, and updateStats: Function. As you can see, not all of them are numbers.

Another issue is that a string can be anything, so updateStats(true, 'blah blah', 3) could become valid if TypeScript didn't stop you.

It would be much better to constrain the specific properties you need to an object within the class with clearly defined properties.

For example:

class Team {
  teamProps: { [key: string]: { for: number, against: number }} = {
    points: { for: 0, against: 0 }
  }

  updateStats = (bool: boolean, property: keyof typeof this.teamProps, increment: number) =>{
    this.teamProps[property][bool ? 'for' : 'against'] += increment;
  }
}

You can access these properties with <Team>.teamProps.points.for instead of <Team>.pointsFor.

about 3 years ago · Juan Pablo Isaza Report

0

You can do nearly everything with TypeScripts typesystem:

TeamProp takes a union of keys (keyof this in this case) and returns only strings, that match ${string}For or ${string}Against.

type TeamProp<K> = K extends `${infer P}For` ? P : K extends `${infer P}Against` ? P : never;

class Team {
    pointsFor: number;
    pointsAgainst: number;

    constructor() {
        this.pointsFor = 0;
        this.pointsAgainst = 0;
    }

    updateStats<P extends TeamProp<keyof this>>(bool: boolean, property: P, increment: number) {
        const key = bool ? `${property}For` : `${property}Against`
        this[key] += increment
    }
}

const t = new Team()

// Works
t.updateStats(true, 'points', 1);

// Argument of type '"foo"' is not assignable to parameter of type '"points"'.
t.updateStats(true, 'foo', 1);
about 3 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error