[英]How to create a decorator that produces a new class property that is a mapping or transformation of the decorated property
I'm trying to figure out how to write a decorator that consumes an already existing class property and generates a mapped or transformed version of that property that also updates every time the value of the original property updates.我试图弄清楚如何编写一个装饰器,它使用已经存在的 class 属性并生成该属性的映射或转换版本,每次原始属性的值更新时也会更新。
For example, @upperCase
would generate a new property (with the key `${DECORATED_PROPERTY}_UPPERCASE`
) that converts the string to upper case, and @double
would generate a new property (with the key `${DECORATED_PROPERTY}_DOUBLE`
) that doubles the value of every number in an array.例如,
@upperCase
将生成一个新属性(使用键`${DECORATED_PROPERTY}_UPPERCASE`
)将字符串转换为大写, @double
将生成一个新属性(使用键`${DECORATED_PROPERTY}_DOUBLE`
)将数组中每个数字的值加倍。
class MyClass {
@upperCase word = 'hamburger';
@double numbers = [1, 2, 3, 4];
}
const foo = new MyClass();
console.log(foo.word_UPPERCASE); // 'HAMBURGER'
console.log(foo.numbers_DOUBLE); // [2, 4, 6, 8]
foo.word = 'new word';
// See the derived property update in accordance with the original when the original changes value
foo.word_UPPERCASE = 'NEW WORD';
I've played around with Object.defineProperty
and the get
and set
properties on it, but nothing seems to work.我玩过
Object.defineProperty
以及它的get
和set
属性,但似乎没有任何效果。 For example, when I try this implementation for @upperCase
:例如,当我为
@upperCase
尝试此实现时:
export function upperCase(target:any, propertyKey:string) {
let value:string = target[propertyKey];
const getter = function () {
return value.toUpperCase(); // Error below gets thrown at this line
}
const setter = function (newVal:string) {
value = newVal;
}
Object.defineProperty(target, `${propertyKey}_UPPERCASE`, {
get: getter,
set: setter,
})
}
and use it in the class like @upperCase word:string = 'foobar';
并在 class 中使用它,例如
@upperCase word:string = 'foobar';
, if I then console.log(this['word_UPPERCASE'])
, I get the following error: ,如果我然后
console.log(this['word_UPPERCASE'])
,我会收到以下错误:
TypeError: can't access property "toUpperCase", value is undefined
thrown at the line commented above where the getter
is trying to return value.toUpperCase()
. TypeError: can't access property "toUpperCase", value is undefined
在上面注释的行中抛出getter
试图返回value.toUpperCase()
。
Thanks to Aluan Haddad , the answer is simply:感谢Aluan Haddad ,答案很简单:
function upperCase(target:any, propertyKey:string) {
Object.defineProperty(target, `${propertyKey}_UPPERCASE`, {
get: function () {
return this[propertyKey].toUpperCase();
},
enumerable: true,
})
}
To use:要使用:
class MyClass {
@upperCase word:string = 'hello';
word_UPPERCASE!:string;
constructor() {
console.log(this.word);
console.log(this.word_UPPERCASE);
}
}
// Output:
// hello
// HELLO
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.