如何为属性

时间:2016-12-02 10:40:30

标签: typescript properties decorator enumerable

我想在TypeScript中创建一个装饰器,以便能够使类属性不可枚举。

我在这里找到了一个@enumerable的例子: https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators 但这似乎只适用于方法,而不是属性:

https://www.typescriptlang.org/docs/handbook/decorators.html#property-decorators

  

注意不提供属性描述符作为参数   由于如何初始化属性装饰器,属性装饰器   打字稿。这是因为目前没有机制   在定义原型的成员时描述实例属性,   并且无法观察或修改属性的初始化程序。如   这样,属性装饰器只能用于观察属性   已为一个类声明了特定名称。

有没有办法为类属性创建一个@enumerable装饰器?

由于

2 个答案:

答案 0 :(得分:10)

我最终得到了这个解决方案:

/**
 * @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;
            Object.defineProperty(target, propertyKey, descriptor)
        }
    };
}

用法:

class User {
    id:string;

    @enumerable(false)
    name: string;
}

测试:

   var user = new User();
   user.id = 1;
   user.name = 'John Doe';
   for (key in user){ console.log(key, user[key]);}

输出

id 1

不使用装饰器的相同测试

id 1
name John Doe

答案 1 :(得分:2)

该解决方案实际上不起作用,或者不适用于现代打字稿。但是,以下内容可以做到:

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