Typescript decorators not unique issues
I have the following case, I want to use a decorator to basically change the get of a function, the goal is that the get return if a specific variable has been set or not.
I have the code required to do it but I think I'm not fully understanding how decorators work. I've created the following example on typescript playground: here
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string | symbol // The name of the property
) {
let value = false;
console.log('hit');
return {
get: () => {
return value;
},
set: (val: string) => {
value = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
has you can see from the example, the first instance of the object is correct (check the console)
the second instance though, for some reason is keeping the same context as the first one, any ideas why? or what is wrong here?
angular typescript instance decorator
add a comment |
I have the following case, I want to use a decorator to basically change the get of a function, the goal is that the get return if a specific variable has been set or not.
I have the code required to do it but I think I'm not fully understanding how decorators work. I've created the following example on typescript playground: here
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string | symbol // The name of the property
) {
let value = false;
console.log('hit');
return {
get: () => {
return value;
},
set: (val: string) => {
value = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
has you can see from the example, the first instance of the object is correct (check the console)
the second instance though, for some reason is keeping the same context as the first one, any ideas why? or what is wrong here?
angular typescript instance decorator
add a comment |
I have the following case, I want to use a decorator to basically change the get of a function, the goal is that the get return if a specific variable has been set or not.
I have the code required to do it but I think I'm not fully understanding how decorators work. I've created the following example on typescript playground: here
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string | symbol // The name of the property
) {
let value = false;
console.log('hit');
return {
get: () => {
return value;
},
set: (val: string) => {
value = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
has you can see from the example, the first instance of the object is correct (check the console)
the second instance though, for some reason is keeping the same context as the first one, any ideas why? or what is wrong here?
angular typescript instance decorator
I have the following case, I want to use a decorator to basically change the get of a function, the goal is that the get return if a specific variable has been set or not.
I have the code required to do it but I think I'm not fully understanding how decorators work. I've created the following example on typescript playground: here
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string | symbol // The name of the property
) {
let value = false;
console.log('hit');
return {
get: () => {
return value;
},
set: (val: string) => {
value = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
has you can see from the example, the first instance of the object is correct (check the console)
the second instance though, for some reason is keeping the same context as the first one, any ideas why? or what is wrong here?
angular typescript instance decorator
angular typescript instance decorator
edited Nov 15 '18 at 15:00
Titian Cernicova-Dragomir
69.3k34865
69.3k34865
asked Nov 15 '18 at 14:59
JoaoglJoaogl
265
265
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
The problem is that your decorator is invokes exactly once per class per decorated field. So the arrow functions inside the decorator will capture that value
variable and will use it for all instances of the decorated class.
You should not keep instance data in decorator function variables (because as explained above they will be shared) You can keep the data on the current instance which, if you use a regular function, is accessible inside get/set functions using this
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string // The name of the property
): any {
console.log('hit');
return {
get: function () {
return !!this[propertyKey + 'value'];
},
set: function(val: string) {
this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322218%2ftypescript-decorators-not-unique-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem is that your decorator is invokes exactly once per class per decorated field. So the arrow functions inside the decorator will capture that value
variable and will use it for all instances of the decorated class.
You should not keep instance data in decorator function variables (because as explained above they will be shared) You can keep the data on the current instance which, if you use a regular function, is accessible inside get/set functions using this
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string // The name of the property
): any {
console.log('hit');
return {
get: function () {
return !!this[propertyKey + 'value'];
},
set: function(val: string) {
this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
add a comment |
The problem is that your decorator is invokes exactly once per class per decorated field. So the arrow functions inside the decorator will capture that value
variable and will use it for all instances of the decorated class.
You should not keep instance data in decorator function variables (because as explained above they will be shared) You can keep the data on the current instance which, if you use a regular function, is accessible inside get/set functions using this
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string // The name of the property
): any {
console.log('hit');
return {
get: function () {
return !!this[propertyKey + 'value'];
},
set: function(val: string) {
this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
add a comment |
The problem is that your decorator is invokes exactly once per class per decorated field. So the arrow functions inside the decorator will capture that value
variable and will use it for all instances of the decorated class.
You should not keep instance data in decorator function variables (because as explained above they will be shared) You can keep the data on the current instance which, if you use a regular function, is accessible inside get/set functions using this
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string // The name of the property
): any {
console.log('hit');
return {
get: function () {
return !!this[propertyKey + 'value'];
},
set: function(val: string) {
this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
The problem is that your decorator is invokes exactly once per class per decorated field. So the arrow functions inside the decorator will capture that value
variable and will use it for all instances of the decorated class.
You should not keep instance data in decorator function variables (because as explained above they will be shared) You can keep the data on the current instance which, if you use a regular function, is accessible inside get/set functions using this
function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string // The name of the property
): any {
console.log('hit');
return {
get: function () {
return !!this[propertyKey + 'value'];
},
set: function(val: string) {
this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
},
enumerable: true,
configurable: true
};
}
class PropertyDecoratorExample {
@PropertyDecorator
name: string;
@PropertyDecorator
name2: string;
constructor() {
console.log('New instance');
console.log(this.name, 'should be false');
this.name = 'hey';
console.log(this.name, 'should be true');
console.log(this.name2, 'should be false');
}
}
new PropertyDecoratorExample();
new PropertyDecoratorExample();
answered Nov 15 '18 at 15:08
Titian Cernicova-DragomirTitian Cernicova-Dragomir
69.3k34865
69.3k34865
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322218%2ftypescript-decorators-not-unique-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown