I am having a difficult time understanding how to use Typescript decorators
. I have this code:
class Address {
private street: string;
private city: string;
private state: string;
private zipCode: string;
@displayName("Street")
get streetHtml() { return this.street; }
@displayName("City")
get cityHtml() { return this.city; }
@displayName("State")
get stateHtml() { return this.state; }
@displayName("Zip Code")
get zipCodeHtml() { return this.zipCode; }
public static map(input: any) {
let address = new Address();
address.street = input.street;
address.city = input.city;
address.state = input.state;
address.zipCode = input.zipCode;
return address;
}
}
function displayName(name: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let label: HTMLLabelElement = document.createElement('label');
label.innerHTML = name;
return label;
};
}
var address = Address.map({ street: "123 My St", city: "Boise", state: "ID", zipCode: "83709" })
console.log(address.cityHtml);
However, the only thing this is doing is returning "Boise". How do I get at the decorator stuff? I did enable "experimentalDecorators": true
, in my tsconfig
.
As commented by @JohnWhite, the getters in your class return a string (that's being inferred by the compiler from the return type), but the decorator you're asking for changes that to return a HTMLLabelElement
.
This might create difficulties for you in compile time, or end up in runtime errors.
With that being said, to answer your question:
What you return in the decorator isn't the returned value of the accessor, as the docs say :
If the accessor decorator returns a value, it will be used as the Property Descriptor for the member
What you need to do is to change the "Property Descriptor" so that it returns your desired value:
function displayName(name: string) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor.get = () => {
let label: HTMLLabelElement = document.createElement('label');
label.innerHTML = name;
return label;
}
};
}
After posting my answer I noticed that you want to get:
<label>Boise</label>
But how you tried to implement it (and my answer) returns:
<label>City</label>
In order to get the desired result we need to change my code a bit:
function displayName(name: string) {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor.get = function() {
let label: HTMLLabelElement = document.createElement('label');
label.innerHTML = this[name.toLowerCase()];
return label;
}
};
}
Where the changes are:
this
will point to the class instance instead of the window. this[name.toLowerCase()]
instead of name
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.