typescriptlodash

Using a propertyPath object in typescript doesn't seem to recognise properties within an array


So I am looking at this piece of code that seems like it never worked. It's basically finding a path in a json and updating its values.

So it uses lodash and when I did into it, the type it is expecting is:

type PropertyPath = Many<PropertyName>;
/** Common interface between Arrays and jQuery objects */

This piece of code uses this type like so:

import { PropertyPath, set } from 'lodash';

export async function setConfig(
  service: string,
  path: PropertyPath,
  value: number | boolean | string
) {
  const config: Record<string, unknown> = await getConfig(
    SERVICES[service]
  );

  set(config, path, value);
...// more code to update the config but the issue is with the above
})

So in the code that calls this method, it goes like so:

  const epic = ['epic', 'reprint', 'enabled'];
  await setConfig('gaming', epic, true);

So based off this example, we are hoping in the gaming service, that we can change the flag located within this json path epic.reprint.enabled to be set to true.

However, I notice it never changed the flag. I do have a workaround way which doesn't use property path type to update the flags, but as this code is used in many places, I was hoping if someone knows how to pass in the path values correctly for this PropertyPath type so that we can update the flags this way.

UPDATE

So the structure is like so:

epic: {
    reprint: { enabled: false }
}

Also the set code we have is like this:

 interface LoDashStatic {
        /**
         * Sets the value at path of object. If a portion of path doesn’t exist it’s created. Arrays are created for
         * missing index properties while objects are created for all other missing properties. Use _.setWith to
         * customize path creation.
         *
         * @param object The object to modify.
         * @param path The path of the property to set.
         * @param value The value to set.
         * @return Returns object.
         */
        set<T extends object>(object: T, path: PropertyPath, value: any): T;
        /**
         * @see _.set
         */
        set<TResult>(object: object, path: PropertyPath, value: any): TResult;
    }

Solution

  • Without knowing the shape of config, this is the shape it must be for you to update that flag in the way you've defined.

    config = {
    epic:{reprint:{enabled:false}}
    }
    

    Assuming the above is the correct shape of config, run the snippet below update it's value.

    const config = {
      epic: {
        reprint: {
          enabled: false
        }
      }
    }
    console.log("before setting", config.epic.reprint.enabled)
    const result = _.set(config, ["epic", "reprint", "enabled"], true)
    
    
    console.log("returned from set", result.epic.reprint.enabled)
    console.log("mutated object", config.epic.reprint.enabled)
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
    

    So the first steps in debugging your application is to verify the structure of config