typescripttype-annotation

How to safely refer to a parameterised property of an object in Typescript?


I have a function that receives an object as parameter and accesses one of its properties, determined by another parameter. Something like this:

// js code
function setProperty(subject, property, value) {
    subject[property] = value;
}

How do I type-annotate this function in a way that makes sure the property param is a key of the subject param, and the value param has the same type?

If it helps, I expect the property param to always be a literal value (a "hard coded" value, not a variable), so that's an acceptable constraint.


Solution

  • You can use generics, extends, and keyof to achieve this sort of functionality. For example:

    interface Subject {
        a: string,
        b: number
    }
    
    function setProperty<T extends keyof Subject>(subject: Subject, property: T, value: Subject[T]) {
        subject[property] = value;
    }
    
    const test: Subject = { a: 'test', b: 2 };
    
    setProperty(test, 'b', 'test'); // Won't compile: Argument of type 'string' is not assignable to parameter of type 'number'.