Reputation: 33
I am writing a Vanilla Typescript Program, as shown below
class DecoratorClass{
@HelloWorld
public property1:string="Siddu Rocks"
}
function HelloWorld(target:any,propertyName:string){
console.log("The Class Target and prop names are:"+target[propertyName] + "," +
propertyName)
}
I am getting the output as The Class Target and prop names are:undefined,property1 instead of The Class Target and prop names are: Siddu Rocks,property1
Why I am getting the property value as undefined, Is there anything I am missing here? I tried checking multiple blogs but no avail
Kindly help me
Upvotes: 0
Views: 2133
Reputation: 39
function Min(limit:number){
return (target:Object,propertyKey:string) => {
let value:string;
console.log("Orignal Value ",target[propertyKey]); // undefined
console.log("Original Value ", this[propertyKey]); //undefined
const getter = function() {
return value;
}
Object.defineProperty(target,propertyKey,{
get:getter,
set:function(newVal:string){
if (newVal.length < limit) {
let error:ValidationError = {
type: propertyKey,
message:`Your password must be greater than ${limit}`
};
let errors = this["errors"];
console.log("ERRORS: ",errors);
// Here I wanted to update the errors field, and I accessed it using this["errors"]. This will get all the errors and push the new error.
errors.push(error);
Object.defineProperty(target,"errors",{
value:errors
})
}else{
value = newVal
}
}
})
}
}
type ValidationError = {
type: string,
message: string
}
class User {
errors:ValidationError[] = [];
@Min(8)
password:string;
@Min(7)
username:string;
constructor(password:string,username:string) {
this.password = password;
this.username = username;
}
}
const user = new User("12345","fahad");
console.log(user.errors);
My output is following:
Orignal Value undefined
Orignal Value undefined
ERRORS: []
ERRORS: [
{ type: 'password', message: 'Your password must be greater than 8' }
]
[
{ type: 'password', message: 'Your password must be greater than 8' },
{ type: 'username', message: 'Your password must be greater than 7' }
]
Upvotes: -1
Reputation: 26327
A common misconception: target
in the decorator is actually not an instance of the class, but the class prototype itself.
Also, the transpiled JavaScript actually looks something like this (even when using the ESNext target):
class DecoratorClass {
constructor() {
this.property1 = "Siddu Rocks";
}
}
which is why when you attempt to log target[propertyName]
, gives you undefined
. It's simply not declared on the class, but rather set when you create an instance of the class.
From the link above, there is also this note:
A Property Descriptor is not provided as an argument to a property decorator due to how property decorators are initialized in TypeScript. This is because there is currently no mechanism to describe an instance property when defining members of a prototype, and no way to observe or modify the initializer for a property. The return value is ignored too. As such, a property decorator can only be used to observe that a property of a specific name has been declared for a class.
Essentially, class decorators can only be used to modify the property (replace with getters/setters, observe changes to it, validate on change, etc).
Upvotes: 2
Reputation: 54658
Property decorators are modifying the class not the instance. So property1 is not set at the time HelloWorld
is called.
Upvotes: 0