为什么 enumerable: false 不级联到 TypeScript 中的 inherited 类?
Why does enumerable: false not cascade to inherited classes in TypeScript?
如果我使用 TypeScript 和下面的方法将 属性 标记为 @enumerable(false)
,则扩展父 class 的子 classes 将此可枚举标记为false 将具有 属性 但它将是可枚举的 this answer.
export {}
declare global {
function enumerable(value: boolean): any;
}
const _global = (global /* node */ || window /* browser */) as any;
/**
* @enumerable decorator that sets the enumerable property of a class field to false.
* @param value true|false
*/
_global.enumerable = function(value: boolean): any {
return function (target: any, propertyKey: string) {
let descriptor = Object.getOwnPropertyDescriptor(target, propertyKey) || {};
if (descriptor.enumerable != value) {
descriptor.configurable = true;
descriptor.writable = true;
descriptor.enumerable = value;
Object.defineProperty(target, propertyKey, descriptor)
}
};
}
这是我的层次结构:
class BaseObject {
@enumerable(false)
public _metadata: any = {
id: 'number',
name: 'string'
};
}
class ContainerObject extends BaseObject {
// ...
}
class CanvasObject extends BaseObject {
// ...
}
下面是描述符在运行时的值:
var canvas = new CanvasObject();
console.log('Metadata Descriptor: ');
console.log(Object.getOwnPropertyDescriptor(canvas, '_metadata'));
Metadata Descriptor:
{ value:
{ beanId: 'number',
name: 'string' },
writable: true,
enumerable: true,
configurable: true }
如何确保此 属性 在父 class 和所有后续继承的 class 中是 enumerable: false
?
这是由于 class 声明中的 class 原型应用了装饰器。由于 _metadata
是实例 属性(它被脱糖为 constructor() { this._metadata = ... }
),enumerable
装饰器不会影响它。
下面是一个 enumerable
装饰器的例子,它可以应用于原型(通常是方法)和实例属性:
function enumerable(value: boolean) {
return (target: any, prop: string, descriptor?: PropertyDescriptor) => {
if (descriptor) {
// prototype property
descriptor.enumerable = value;
} else {
// instance property
let propSymbol = Symbol(prop);
Object.defineProperty(target, prop, {
configurable: true,
enumerable: value,
get() { return this[propSymbol] },
set(value) { this[propSymbol] = value }
});
}
};
}
请注意,为了处理 _metadata = ...
属性 初始值设定项,描述符应包含 set
访问器以捕获 属性 赋值。
如果我使用 TypeScript 和下面的方法将 属性 标记为 @enumerable(false)
,则扩展父 class 的子 classes 将此可枚举标记为false 将具有 属性 但它将是可枚举的 this answer.
export {}
declare global {
function enumerable(value: boolean): any;
}
const _global = (global /* node */ || window /* browser */) as any;
/**
* @enumerable decorator that sets the enumerable property of a class field to false.
* @param value true|false
*/
_global.enumerable = function(value: boolean): any {
return function (target: any, propertyKey: string) {
let descriptor = Object.getOwnPropertyDescriptor(target, propertyKey) || {};
if (descriptor.enumerable != value) {
descriptor.configurable = true;
descriptor.writable = true;
descriptor.enumerable = value;
Object.defineProperty(target, propertyKey, descriptor)
}
};
}
这是我的层次结构:
class BaseObject {
@enumerable(false)
public _metadata: any = {
id: 'number',
name: 'string'
};
}
class ContainerObject extends BaseObject {
// ...
}
class CanvasObject extends BaseObject {
// ...
}
下面是描述符在运行时的值:
var canvas = new CanvasObject();
console.log('Metadata Descriptor: ');
console.log(Object.getOwnPropertyDescriptor(canvas, '_metadata'));
Metadata Descriptor:
{ value:
{ beanId: 'number',
name: 'string' },
writable: true,
enumerable: true,
configurable: true }
如何确保此 属性 在父 class 和所有后续继承的 class 中是 enumerable: false
?
这是由于 class 声明中的 class 原型应用了装饰器。由于 _metadata
是实例 属性(它被脱糖为 constructor() { this._metadata = ... }
),enumerable
装饰器不会影响它。
下面是一个 enumerable
装饰器的例子,它可以应用于原型(通常是方法)和实例属性:
function enumerable(value: boolean) {
return (target: any, prop: string, descriptor?: PropertyDescriptor) => {
if (descriptor) {
// prototype property
descriptor.enumerable = value;
} else {
// instance property
let propSymbol = Symbol(prop);
Object.defineProperty(target, prop, {
configurable: true,
enumerable: value,
get() { return this[propSymbol] },
set(value) { this[propSymbol] = value }
});
}
};
}
请注意,为了处理 _metadata = ...
属性 初始值设定项,描述符应包含 set
访问器以捕获 属性 赋值。