Skip to content

When using the native method 'defineProperty ' to define a 'Getter' for a class, the compiler error! #14650

Closed

Description

@ulivz

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?

Activity

  1. ulivz commented on Mar 14, 2017

    @ulivz
    Author

    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;
        }
    
    }
  2. RyanCavanaugh commented on Mar 14, 2017

    @RyanCavanaugh
    Member

    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 { }
  3. ulivz commented on Mar 15, 2017

    @ulivz
    Author

    Can the name of interface and class be the same name? well, I didn‘t write it before. Just wrote a simple interface inheritance

  4. kitsonk commented on Mar 15, 2017

    @kitsonk
    Contributor

    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.

  5. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions