The following function should create a proxy object with a specific handler, but typescript is throwing a type error when I try it that way.
function createProxiedObject<T extends object>(obj: T): T {
const handler = {
set(obj: {[key: string]: any}, prop: string, value: any) {
console.log(`changed ${prop} from ${obj[prop]} to ${value}`);
obj[prop] = value;
return true;
}
};
return new Proxy(obj, handler)
}
Error:
Type '{ [key: string]: any; }' is not assignable to type 'T'.
'{ [key: string]: any; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.(2322)
It does not make a difference when I check if obj
is of type object
.
I can't see why this shouldn't work. It matches with the ProxyConstructor interface:
interface ProxyConstructor {
// ...
new <T extends object>(target: T, handler: ProxyHandler<T>): T;
}
What am I doing wrong here?
If we take a look at Proxy
's type definition we will see that it accepts a generic parameter:
interface ProxyConstructor {
/**
* Creates a Proxy object. The Proxy object allows you to create an object that can be used in place of the
* original object, but which may redefine fundamental Object operations like getting, setting, and defining
* properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs.
* @param target A target object to wrap with Proxy.
* @param handler An object whose properties define the behavior of Proxy when an operation is attempted on it.
*/
new <T extends object>(target: T, handler: ProxyHandler<T>): T;
}
declare var Proxy: ProxyConstructor;
You can manually pass the correct type, instead of letting the typescript do it automatically, thus solutions looks like this:
function createProxiedObject<T extends object>(obj: T): T {
const handler = {
set(obj: { [key: string]: any }, prop: string, value: any) {
console.log(`changed ${prop} from ${obj[prop]} to ${value}`);
obj[prop] = value;
return true;
},
};
return new Proxy<T>(obj, handler);
}