Renaming and deprecating fields using JavaScript proxies: The cool and easy way

Shit happens. Specs change. Services change. And property names have to change along with that. If you’re writing open source software or packages that anyone relies on, sooner or later you’ll probably have to rename and deprecate fields. And before you break things in a new version, you’ll want to notify developers in some upcoming versions that a field will be renamed and dropped in a later version. A simple way to do this is by using proxies (probably one of the most under utilized JavaScript features).

In order to accomplish this, you can proxy an object by manipulating the getter when it’s called. In the example code below, we’ll add a warning if someone is accessing a field we want to rename. And if they are access the new naming, we’ll just return the original value.


  // Create a map of old names to new names (e.g. first => firstName)
  // First value is the current property, second is the new
  const PROPERTY_DEPRECATIONS = new Map([
    ["first", "firstName"],
    ["last", "lastName"]
  ])

  // Helper to get a key by it's value
  // (e.g. get "first" for "firstName"
  const getByValue = (map, searchValue) => {
    for (let [key, value] of map.entries()) {
      if (value === searchValue) return key;
    }
  }

  
  const deprecator = (originalObject, propertyDeprecations) => {
    return new Proxy(originalObject, {
      get: (obj, property) => {
        if (getByValue(PROP_DEPRECATIONS, property)) {
          const originalProperty = getByValue(PROPERTY_DEPRECATIONS, property)
          return Reflect.get(obj, originalProperty)
        }
        if (PROP_DEPRECATIONS.has(property)) {
          console.warn(`Field deprecation: "${property}" will be deprecated in a future version. Please use "${PROP_DEPRECATIONS.get(property)}" instead."`)
        }
        return Reflect.get(obj, property)
      }
    })
  }

  const person = {
    "first": "Bob",
    "last": "Bobberson"
  }

  const personWithDeprecations = deprecator(person, PROPERTY_DEPRECATIONS)

  console.log(person.first) // Will get warning to use "firstName"
  console.log(person.firstName) // Will return value for "first"

If you want to read more about proxies, you can do so here.