[英]How to create Typescript decorator that sets all class properties as non-enumerable based on property name starting with “_”?
How do you get a Typescript class decorator to call a method that sets any property or method starting with an "_" as non-enumerable property (essentially making it private for serialization purposes)?如何获得 Typescript class 装饰器来调用将任何以“_”开头的属性或方法设置为不可枚举属性的方法(本质上将其设为私有以用于序列化目的)?
Imagine there's a class that's a base class which every other class in my application will extend from:想象一下,有一个 class 是基础 class ,我的应用程序中的所有其他 class 将从:
class Base {
constructor(data: any){
Object.assign(this, data)
}
_setNonEnumerableProperties(){
Object.keys(this).forEach(key => {
if(key[0] === '_')
Object.defineProperty(this, key, { enumerable: false })
})
}
}
And then I have a User class like this:然后我有一个像这样的用户 class :
@nonEnumerablePrivateMembers
class User extends Base {
public name: string
public email: string
private _active: boolean
}
And I create and JSON stringify a User instance like this:我创建并 JSON 像这样对 User 实例进行字符串化:
const user = new User({name: 'John', email: 'john@example.com', _active: false})
const jsonUser = JSON.stringify(user)
console.log(jsonUser)
I expect the output to be this:我希望 output 是这样的:
{ "name": "John", "email": "john@example.com" }
and not this:而不是这个:
{ "name": "John", "email": "john@example.com", "_active": false }
Note that it doesn't include the _active
property.请注意,它不包括
_active
属性。
I need to know how to write nonEnumerablePrivateMembers
decorator that would call the _setNonEnumerableProperties
method on the Base class upon a new instance of the extended class.我需要知道如何编写
nonEnumerablePrivateMembers
装饰器,它会在扩展 class 的新实例上调用 Base class 上的_setNonEnumerableProperties
方法。
Any suggestions?有什么建议么?
Overriding the constructor appears to work as intended:覆盖构造函数似乎按预期工作:
interface Class<T> {
new(...args: any[]): T
}
function nonEnumerablePrivateMembers<T extends Class<Base>>(cls: T): T {
return class extends cls {
constructor(...args: any[]) {
super(...args);
this._setNonEnumerableProperties();
}
}
}
I'm sure someone with better TypeScript skills can modify this to be a bit cleaner, but based on the TypeScript decorator docs you can have something like this:我敢肯定,拥有更好的 TypeScript 技能的人可以将其修改为更简洁,但基于TypeScript 装饰器文档,您可以拥有以下内容:
function fixEnumerables<T extends { new (...args: any[]): {} }>(
constructor: T
) {
return class extends constructor {
constructor(...data: any[]) {
super(data);
Object.assign(this, data[0]);
Object.keys(this).forEach(key => {
if (key[0] === "_") {
console.log(`Freezing "${key}"`);
Object.defineProperty(this, key, { enumerable: false });
}
});
}
};
}
@fixEnumerables
class User {
public name: string;
public email: string;
private _active: boolean;
constructor(data: any) {}
}
const x = new User({ name: "Sam", email: "email@example.com", _active: false });
console.log(JSON.stringify(x));
// Output
// Freezing "_active"
// {"name":"Sam", "email": "email@example.com"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.