2

I need a function, that alters a specific variable in my Object:

function updateField(fieldname, newValue){
  return {...this.oldObject, fieldname: newValue};
}

And I want to make it Typesafe. Type of fieldName is typeof clazz, but what is the Type of newValue? I know Typescripts Pick, so full typing would be something like:

updateField(fieldname: typeof Clazz, newValue: Pick<Clazz, fieldname>): Clazz

but I don't know how to go with non-constant strings. Is that even possible in TS?

Dániel Somogyi
  • 730
  • 7
  • 19

1 Answers1

2

You can restrict a filed name to be a valid object key using keyof operator. To get a type of value you can use lookup type T[K] where T is the object type and K is the key type:

const foo = {
    a: 1,
    b: 'some string'
};

function update<T, K extends keyof T>(obj: T, key: K, value: T[K]): T {
    return {
        ...obj,
        [key]: value,
    }
}

update(foo, 'a', 2); // OK
update(foo, 'b', 2); // Error: Argument of type '2' is not assignable to parameter of type 'string'
update(foo, 'c', 2); // Error: Argument of type '"c"' is not assignable to parameter of type '"a" | "b"'

Playground

Aleksey L.
  • 35,047
  • 10
  • 74
  • 84
  • 1
    That's perfectly what I needed. Just hoped i can do that with Pick, instead typing around. – Dániel Somogyi Nov 18 '19 at 14:07
  • `Pick` would create a "object type" with a key and value (e.g. `{ a: string }`) but what you're looking for is key type and value type separated – Aleksey L. Nov 19 '19 at 08:35