是否可以在打字稿中创建动态获取器/设置器?

Vla*_*lad 6 class dynamic typescript typescript2.0

我是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);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }
Run Code Online (Sandbox Code Playgroud)

使用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);                                            
              }                                                                        
            },                                                                         
          });                                                                          
        }                                                                              
      } 
    }

Run Code Online (Sandbox Code Playgroud)

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'.
Run Code Online (Sandbox Code Playgroud)

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

Vla*_*lad 8

感谢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);                                            
          }                                                                        
        },                                                                         
      });                                                                          
    }                                                                              
  } 
}
Run Code Online (Sandbox Code Playgroud)

  • 您好,这似乎是一个很好的解决方案,但是当我尝试访问该属性 (`MyClass.myPropertyName`) 时,我不断收到类型 'MyClass'` 错误中不存在的 `Property 'myPropertyName'。有想法该怎么解决这个吗?谢谢! (2认同)