I want to create a decorator in TypeScript in order to be able to make a class property not enumerable.
I found an example of @enumerable
here:
https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators
but that only seems to work for methods, not properties:
https://www.typescriptlang.org/docs/handbook/decorators.html#property-decorators
NOTE A Property Descriptor is not provided as an argument to a property decorator due to how property decorators are initialized in TypeScript. This is because there is currently no mechanism to describe an instance property when defining members of a prototype, and no way to observe or modify the initializer for a property. As such, a property decorator can only be used to observe that a property of a specific name has been declared for a class.
Is there a way to create a @enumerable
decorator for a class property?
Thanks
I ended up with this solution:
/**
* @enumerable decorator that sets the enumerable property of a class field to false.
* @param value true|false
*/
function enumerable(value: boolean) {
return function (target: any, propertyKey: string) {
let descriptor = Object.getOwnPropertyDescriptor(target, propertyKey) || {};
if (descriptor.enumerable != value) {
descriptor.enumerable = value;
descriptor.writable= true;
Object.defineProperty(target, propertyKey, descriptor)
}
};
}
Usage:
class User {
id:string;
@enumerable(false)
name: string;
}
Testing:
var user = new User();
user.id = 1;
user.name = 'John Doe';
for (key in user){ console.log(key, user[key]);}
Output
id 1
Same test without the use of the decorator
id 1
name John Doe
This solution doesn't actually work, or doesn't work with modern typescript. The following does however:
const enumerable: {
(target: any, name: string): void;
(target: any, name: string, desc: PropertyDescriptor): PropertyDescriptor;
} = (target: any, name: string, desc?: any) => {
if(desc) {
desc.enumerable = true;
return desc;
}
Object.defineProperty(target, name, {
set(value) {
Object.defineProperty(this, name, {
value, enumerable: true, writable: true, configurable: true,
});
},
enumerable: true,
configurable: true,
});
};
const nonenumerable: {
(target: any, name: string): void;
(target: any, name: string, desc: PropertyDescriptor): PropertyDescriptor;
} = (target: any, name: string, desc?: any) => {
if(desc) {
desc.enumerable = false;
return desc;
}
Object.defineProperty(target, name, {
set(value) {
Object.defineProperty(this, name, {
value, writable: true, configurable: true,
});
},
configurable: true,
});
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With