Class 可以在typescript中创建动态getter/setter吗?

Class 可以在typescript中创建动态getter/setter吗?,class,typescript,dynamic,typescript2.0,Class,Typescript,Dynamic,Typescript2.0,我是typescript新手,我正在尝试将我们的应用程序从es2016重写为typescript。 我的任务是拥有一个具有数据属性的类,并使数据对象中的每个元素作为类属性可用 我被这段javascript代码卡住了: for(let key in this.data) { Object.defineProperty(this, key, {

我是typescript新手,我正在尝试将我们的应用程序从es2016重写为typescript。 我的任务是拥有一个具有数据属性的类,并使数据对象中的每个元素作为类属性可用

我被这段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);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }
对typescript使用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-TES2016--lib“ES2016”、“dom”模型。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'.
models.ts(33,40):错误TS2345:类型为“{get:(value:any)=>any;set:(value:any)=>void;}”的参数不能分配给类型为“PropertyDescriptor&ThistType”的参数。
类型“{get:(value:any)=>any;set:(value:any)=>void;}”不能分配给类型“PropertyDescriptor”。
属性“get”的类型不兼容。
类型'(值:any)=>any'不可分配给类型'()=>any'。

我不知道如何解决这个问题。

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

如果您只想将加载的(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);
如果您确实想要一个包含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));
多亏了她,她帮我找到了解决办法。我会把它贴在这里:

错误在于getter有一个value参数,即使getter 没有传递任何值

我将其替换为get:function(){returnthis.data[key];},现在 唯一的错误是类中有一个超级调用 如果该类扩展了另一个类,则需要

而且,访问器中的这个并不引用类实例, 但是为它们使用箭头函数应该可以解决这个问题

试试这个:


您好,这似乎是一个很好的解决方案,但当我尝试访问属性时(
MyClass.myPropertyName
),我不断发现类型“MyClass”上不存在属性“myPropertyName”)。有没有办法解决这个问题?谢谢我还遇到了一个问题,财产不存在,你如何解决这个问题@维亚德?
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);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }                                                                              
  } 
}