Modify object property with a variable in typescript

Viewed 3000

In js I have a function which modify properties of an object contained in a list of object according to parameters:

function edit(object, key, property, value){
  object[key][property] = value;
}

How would I manage to do the same function in TypeScript ?

From now I've made this:

function edit(object: ObjectList, key: string, property: string, value: number){
  object[key][property] = value;
}

But that doesn't work and gives me a Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; mastery: number; parent_skill: number; access_level: number; cost: string; cost_value: number; background_color: number[]; font_color: number[]; description: string; required_skills: number[]; }'. No index signature with a parameter of type 'string' was found on type '{ name: string; mastery: number; parent_skill: number; access_level: number; cost: string; cost_value: number; background_color: number[]; font_color: number[]; description: string; required_skills: number[]; }'

I want to be able to call the function like this:

edit(myObject, "first", "oneProperty", "newValue1");

And the result would be that my "first" item in myObject would have "newValue1" for its "oneProperty" property.

More informations: My object list

type SkillList = {
  [key: string]: Skill;
};

My object

type Skill = {
  name: string;
  mastery: number;
  parent_skill: number;
  access_level: number;
  cost: string;
  cost_value: number;
  background_color: number[];
  font_color: number[];
  description: string;
  required_skills: number[];
};
1 Answers

The answer would be a generic function:

The Code

function edit<O extends ObjectList, K extends keyof O, P extends keyof O[K]>(object: O, key: K, property: P, value: O[K][P]){
  object[key][property] = value;
}

Playground

Explanation

First, we have a generic type O which lets us use the inputed object type, e.g. to potentially narrow [key: string]: Skill;.

Then we have generic type K which refers to all of the keys in O/object.

After that we have generic type P which refers to all the properties in object[key].

Finally we have O[K][P] which tells typescript to use the type of object[key][property]. This is probably the most useful part, since it prevents overriding strings with numbers, for example edit(mySkillObject, "first", "name", "newValue1");

Related