DEV Community

jcarloscandela
jcarloscandela

Posted on

Safe reflection using TypeScript

Reflection

Reflection is a good way to avoid redundant code. I give you an example, imagine that we have the following code:

if(object.propertyA != null){
    console.log(object.propertyA);
}

if(object.propertyB != null){
    console.log(object.propertyB);
}

if(object.propertyC != null){
    console.log(object.propertyC);
}
Enter fullscreen mode Exit fullscreen mode

A good way to improve it is avoiding the repeated code as follows. We create an array of strings with the properties on which we want to execute the action

const properties: string['propertyA', 'propertyB', 'propertyC'];

properties.forEach(property => {
    const value = Reflect.get(obj, property)
    if(value != null){
        console.log(value);
    }
});
Enter fullscreen mode Exit fullscreen mode

So far so good, but what happens if we modify the name of the variables of the type of the object? Code we implemented in the past would fail and we wouldn't notice when we made the change.

How can we solve this? Creating a Proxy class

Proxy

What is a proxy? A proxy object enables you to create a proxy for another object, which can intercept and redefine fundamental operations for that object.

First of all we must retrieve the type we are using from the original object which is the following:

class ObjectType {
    propertyA: string;
    propertyB: number;
    propertyC: boolean;
}
Enter fullscreen mode Exit fullscreen mode

How do we extract the properties of the object? Using the next function:

private proxiedPropertiesOf<TObj>() {
    return new Proxy({}, {
        get: (_, prop) => prop,
        set: () => {
        throw Error('Set not supported');
        },
    }) as {
        [P in keyof TObj]?: P;
    };
}
Enter fullscreen mode Exit fullscreen mode

This allows us to extract the types safely and the code would look like this:

const typeProperties = this.proxiedPropertiesOf<ObjectType>();

const properties: string[] =
    [
        typeProperties.propertyA, 
        typeProperties.propertyB, 
        typeProperties.propertyC
    ];          
Enter fullscreen mode Exit fullscreen mode

From now on, if we make any changes to the ObjectType model, if we modify the name of any property or remove it, the TypeScript compiler itself will show us the error.

I hope it has been useful, thank you for your time :)

Much of the information comes from the following link

Top comments (0)