Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I strongly type a function returning a property of an object?

I have a function named getPropertyReference that returns a reference of a property in an object. It’s mostly for my sanity to prevent typing this.object.myNestedObject.property = ... over and over.

Here’s the complete function:

export function getPropertyReference(object: {[key: PropertyKey]: any}, prop: PropertyKey): any {
    return {
        get value(): any {
            return object[prop];
        },

        set value(to: any) {
            object[prop] = to;
        }
    }.value; // return the getters and setters without having to access ref.value
}

Usage goes something along the lines of

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const ref = getPropertyReference(this.object.myNestedObject, "foo");

ref = 4;

console.log(ref); // 4
console.log(this.object.myNestedObject.foo); // 4

// etc

That code works fine. However, it has a return type of any, and it would be much nicer to get a return type of object[prop]. My code looks like this:

export function getPropertyReference<O = {[key: PropertyKey]: any}, K = keyof O>(object: O, prop: K): O[K] {
    // same code here
}

Typescript complains about this here. "Type ‘K’ cannot be used to index type ‘O’." How can I fix this?

>Solution :

You’re very close with the last type you tried. Problem is just that you did = in the generic definition, when you should have used extends. For example, K = keyof O means K can be absolutely any type, but will default to keyof O if no type is supplied. Instead, it needs to be K extends keyof O, which will restrict K to the keys of the object.

export function getPropertyReference<
  O extends { [key: string]: any },
  K extends keyof O
>(object: O, prop: K): O[K] {
  return {
    get value(): O[K] {
      return object[prop];
    },

    set value(to: O[K]) {
      object[prop] = to;
    },
  }.value;
}

const example = { name: "bob", age: 12 };

let age = getPropertyReference(example, "age"); // number
let error = getPropertyReference(example, "doesNotExist"); // compile time error

Playground link

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading