3

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[];
};
5
  • It gives you a... what exactly? Seems you missed pasting the error. Commented Jul 29, 2020 at 20:32
  • Also, what type signature does ObjectList have? Commented Jul 29, 2020 at 20:32
  • 1
    Thanks @CherryDT I edited. Commented Jul 29, 2020 at 20:34
  • @CherryDT When you said 'You need a type limited to the values existing in the object', do you refer to the Skill object or the SkillList ? Do you mean that a String litteral Types should handle the job ? Commented Jul 29, 2020 at 20:41
  • Skill, but I deleted the comment because I thought it would make more sense to wait for someone more competent in TypeScript than me to write an answer. Commented Jul 29, 2020 at 20:44

1 Answer 1

5

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");

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer and the explanations. It's definitely what I needed to move forward !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.