TypeScript Version: 1.8.0
Code:
// a function used to define targetObject's descriptor from SourceObject's properties
function defineGetter(SourceObject, targetObject) {
Object.keys(SourceObject).forEach(function (key) {
Object.defineProperty(targetObject.prototype, key, {
get: function () {
return SourceObject[key]
},
enumerable: true,
configurable: true
})
})
}
interface IForm {
name: string;
label: string;
value: any;
sequence: number;
width: number;
type: number;
}
class Form {
constructor(form: IForm) {
defineGetter(form, Form);
}
get info() {
return `name is ${this.name}, label is ${this.label}`;
}
}
let form = new Form({
name: '1',
label: '2',
value: 3,
sequence: 4,
width: 5,
type: 6
})
Expected behavior & Actual behavior:
I want to complete my definition of Getter with metadata(a Singleton Object) through a defineGetter () method, It seems to be successful. but, When I manually define another Getter (info), the compiler prompts:
“ error TS2339: Property 'name' does not exist on type 'Form'”
“ error TS2339: Property 'type' does not exist on type 'Form'. ”
I just want to use a function to solve my burden of writing the getter repeatedly,How can I solve this problem?
How can I only write a class in this way 😐:
class Form{
private _form: IForm;
constructor(form: IForm) {
this._form = form;
}
get name() {
return this._form.name;
}
get label() {
return this._form.name;
}
get value() {
return this._form.value;
}
get width() {
return this._form.width;
}
get type() {
return this._form.type;
}
get sequence() {
return this._form.sequence;
}
// extra getter
get info() {
return this.width + this.type;
}
}
Write this:
class Form {
constructor(form: IForm) {
defineGetter(form, Form);
}
get info() {
return `name is ${this.name}, label is ${this.label}`;
}
}
interface Form extends IForm { }
Can the name of interface and class be the same name? well, I didn‘t write it before. Just wrote a simple interface inheritance
Can the name of interface and class be the same name?
It takes advantage of what TypeScript calls "interface merging". When an interface and a class have the same name, it automatically merges the two. This is in part why it is often recommended not to name your interfaces with an I... which is a convention in many other languages, since there some "automagic" that can happen when the names are the same.
It is best to think as the type system in TypeScript as an "overlay" on top of the underlying JavaScript.
Also to properly type your interface, you should be marking properties that only have a getter as readonly in the interface, which will disallow assignment to the properties within the type system, which would more accurately reflect your runtime intent.
Most helpful comment
Write this: