首页 > 解决方案 > 如何创建基于以“_”开头的属性名称将所有类属性设置为不可枚举的 Typescript 装饰器?

问题描述

如何让 Typescript 类装饰器调用一个方法,该方法将任何以“_”开头的属性或方法设置为不可枚举属性(本质上将其设为私有以用于序列化目的)?

想象一下,有一个类是一个基类,我的应用程序中的所有其他类都将从该类扩展:

class Base {
     constructor(data: any){
        Object.assign(this, data)
     }

     _setNonEnumerableProperties(){
        Object.keys(this).forEach(key => {
            if(key[0] === '_')
                Object.defineProperty(this, key, { enumerable: false })
        })
     }
}

然后我有一个像这样的用户类:

@nonEnumerablePrivateMembers
class User extends Base {
     public name: string
     public email: string
     private _active: boolean
}

我创建并 JSON 字符串化一个 User 实例,如下所示:

const user = new User({name: 'John', email: 'john@example.com', _active: false})
const jsonUser = JSON.stringify(user)
console.log(jsonUser)

我希望输出是这样的:

{ "name": "John", "email": "john@example.com" }

而不是这个:

{ "name": "John", "email": "john@example.com", "_active": false }

请注意,它不包括该_active属性。

我需要知道如何编写nonEnumerablePrivateMembers装饰器,它会_setNonEnumerableProperties在扩展类的新实例上调用基类上的方法。

有什么建议么?

标签: javascriptjsontypescriptclassoop

解决方案


覆盖构造函数似乎按预期工作:

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();
    }
  }
}

操场


推荐阅读