是否可以在打字稿中创建动态getter / setter?

时间:2017-07-21 11:15:49

标签: class typescript dynamic typescript2.0

我是打字稿的新手,我试图将我们的应用程序从es2016重写为打字稿。 我的任务是创建一个具有data属性的类,并使数据对象中的每个元素都可用作类属性。

我对这个javascript代码感到困惑:

    for(let key in this.data) {                                                    
      Object.defineProperty(this, key, {                                           
        get: function(value:any) { return this.data[key]; },                       
        set: function(value:any) {                                                 
          if (this.data[key] !== value) {                                          
            this.data[key] = value;                                                
            this.updatedKeys.push(key);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }

对于打字稿使用getter / setter非常容易,但如果我可以动态创建它们,我会感到困惑吗?

    interface IData {                                                               
      id: number;                                                                   
      [propName: string]: any;                                                      
    }                                                                               

    class Model  {                                                 

      protected updatedKeys:string[] = [];                                          

      baseUrl:string = null;                                                        
      data:IData;                                                                   
      fields:IData;

      constructor(data:IData={id:null}, fields:IData={id:null}) {                      
        super()                                                                        
        this.data = data;                                                              
        this.fields = fields;                                                                                                     

        for(let key in this.data) {                                                    
          Object.defineProperty(this, key, {                                           
            get: function(value:any) { return this.data[key]; },                       
            set: function(value:any) {                                                 
              if (this.data[key] !== value) {                                          
                this.data[key] = value;                                                
                this.updatedKeys.push(key);                                            
              }                                                                        
            },                                                                         
          });                                                                          
        }                                                                              
      } 
    }

tsc -t ES2016 --lib "es2016","dom" models.ts

将发出此错误:

models.ts(33,40): error TS2345: Argument of type '{ get: (value: any) => any; set: (value: any) => void; }' is not assignable to parameter of type 'PropertyDescriptor & ThisType<any>'.
  Type '{ get: (value: any) => any; set: (value: any) => void; }' is not assignable to type 'PropertyDescriptor'.
    Types of property 'get' are incompatible.
      Type '(value: any) => any' is not assignable to type '() => any'.

我不知道如何摆脱这个问题。

2 个答案:

答案 0 :(得分:7)

感谢https://github.com/epicgirl1998,她帮我找到了解决方案。我将在此发布:

  

错误是getter有一个值参数,即使是getter   没有传递任何价值

     

我用get:function()替换它{return this.data [key]; }, 现在   唯一的错误是在课堂上只有一个超级电话   如果类扩展另一个类

,则需要      

此外,访问者内部没有引用类实例,   但是使用箭头函数应该修复它

     

试试这个:

interface IData {                                                               
  id: number;                                                                   
  [propName: string]: any;                                                      
}                                                                               

class Model  {                                                 

  protected updatedKeys:string[] = [];                                          

  baseUrl:string = null;                                                        
  data:IData;                                                                   
  fields:IData;

  constructor(data:IData={id:null}, fields:IData={id:null}) {                      

    this.data = data;                                                              
    this.fields = fields;                                                                                                     

    for(let key in this.data) {                                                    
      Object.defineProperty(this, key, {                                           
        get: () => { return this.data[key]; },                       
        set: (value:any) => {                                                 
          if (this.data[key] !== value) {                                          
            this.data[key] = value;                                                
            this.updatedKeys.push(key);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }                                                                              
  } 
}

答案 1 :(得分:0)

在打字稿中,您通常不需要动态创建具有方法和属性的对象。您可以创建类的实例,也可以使用界面键入数据。

如果您只想将加载的(json)数据转换为类型化数据,则可以使用描述json数据结构的接口。

界面描述了演员数据的属性

interface Actor {
    name: string;
    height: number;
}

从某处获取通用json数据

let data : any = getSingleActorData();

将actor键入接口并将其放入actor数组

let actorData : Actor[] = [];
actorData.push(data as Actor);

现在,您的IDE将允许您访问actor变量的名称和高度:

console.log(actorData[0].name);

如果你想要一个完整的对象&#39;使用getter和setter,您可以创建一个Actor类,然后使用您加载的数据对其进行实例化:

class Actor {
    private _name:string;
    private _height:string;
    get name {}
    set name {}
    get height {}
    set height {}
    constructor(name:string, height:number){
    }
}

然后你可以把你的json数据放在一个actor实例中:

actorData.push(new Actor(jsondata.name, jsondata.height));