Refactoring with the Help of Proxies
Today I started refactoring part of an application from one API version to another. In the two versions, some fields are named differently, for example title
was renamed to jobTitle
. This would be an awesome use-case for TypeScript, but this was legacy code and I needed to get this done as fast as possible.
Even so, I still wanted a way to get notified when the old properties were used anywhere in the application. Luckily, you can do this with proxies!
function wrapInRefactorProxy (wrappedObject, whitelistedKeys) {
return new Proxy(wrappedObject, {
get: (object, key) => {
if (!whitelistedKeys.includes(key)) {
console.error('Context for the following error', object)
throw new Error(`Attempted to access non-whitelisted property "${key}"`)
}
return object[key]
}
})
}
This will throw a runtime error whenever a non-whitelisted property is accessed. You can use the wrapper like this:
const person = wrapInRefactorProxy(
{ id: '123123', name: 'Something' },
[ 'id', 'name', 'jobTitle' ]
)
console.log(person.id) // -> 123123
console.log(person.jobTitle) // -> undefined
console.log(person.title) // -> throw Error
Be aware that if you are using Object.assign
, the proxy will get lost:
const assignedPerson = Object.assign({}, person)
console.log(assignedPerson.id) // -> 123123
console.log(assignedPerson.jobTitle) // -> undefined
console.log(assignedPerson.title) // -> undefined (!)
It's not even close to the comfort of TypeScript, but for me it was better than nothing. I could change the API, fix the runtime errors one by one, and at the end had something working without having to do too much digging.