【问题标题】:TypeScript class declaration error with private variable带有私有变量的 TypeScript 类声明错误
【发布时间】:2018-05-07 14:32:54
【问题描述】:

如果我有这样的 TypeScript 类声明:

export class myClass {
  constructor(public aVariable: number) {}
  private aPrivateVariable: number;
}

然后尝试初始化它:

let someVar: myClass[] = [{
  aVariable: 3
}, {
  aVariable: 2
}];

我得到一个错误(至少在 VS Code 中)说:

类型'{ aVariable: number; 中缺少属性'aPrivateVariable' }'。

为什么我不能这样做?

谢谢。

【问题讨论】:

    标签: javascript typescript visual-studio-code


    【解决方案1】:

    想象你的类也有一个使用这个字段的方法:

     export class myClass {
      constructor(public aVariable: number) {}
      private aPrivateVariable: number;
      test(){  }
     }
    

    现在,如果您要执行以下操作:

     const instance: myClass = {
        aVariable: 1,
        test() {
          alert.aPrivateVariable + 1);
        }
     };
    
     instance.test();
    

    它会失败。因此,您还需要添加私有属性。

     let someVar: myClass[] = [{
      aVariable: 3,
      aPrivateVariable: 2,
     }, {
      aVariable: 2,
      aPrivateVariable: 3
     }];
    

    【讨论】:

    • 你的建议不起作用(private variables不能被课外引用);你试过了吗?
    • @Jonas W - 我知道,这就是我想要避免的。我希望这个类有几个内部变量,类的初始化程序不需要引用或声明。这样私有变量仅供内部使用。
    • @mike 然后将其设为可选。
    • 我将把它标记为答案,因为这就是我所做的。这个类很轻,我不想为它创建一个接口。
    • @MikeWitt 顺便问一下,你是如何让它工作的?答案包含不可行的代码。如前所述,您不能从外部分配aPrivateVariable...因为它是 private (TS 类型的此属性可用于故意使类型不兼容)。如果您的代码与列出的代码不同,请考虑发布您最终使用的解决方案。这可能会对未来的读者有所帮助。
    【解决方案2】:

    以您的方式定义对象 ({ aVariable: 2}) 不会将它们实例化为 myClass 对象。这是一个问题,因为 aPrivateVariable 没有被实例化,因为 myClass 构造函数从未被调用,并且您添加的对象与 myClass 包含的不匹配。

    As this excerpt from the typescript handbook on type compatibility states:

    类中的私有成员和受保护成员会影响它们的兼容性。当检查类的实例的兼容性时,如果目标类型包含私有成员,则源类型也必须包含源自同一类的私有成员。同样,这同样适用于具有受保护成员的实例。这允许一个类与其超类的赋值兼容,但不能与来自不同继承层次结构的类兼容,否则它们具有相同的形状。

    解决这个问题的一种方法是使用诸如map() 之类的东西来实例化每个对象

    const someVar: myClass[] = [2,3,1].map(num => myClass(num)) ;

    或者,如果您对对象的形状有信心,可以使用类型强制:

    let someVar: myClass[] = [] as myClass[]

    请谨慎使用这种方法,因为它不能保证数组中包含的内容与类的模型相匹配。

    【讨论】:

      【解决方案3】:
      export class myClass {
         constructor(public aVariable: number) {}
         private aPrivateVariable: number;
      }
      

      正确的方法是像这样初始化你的类:

      const someVar: myClass[] = [
          new myClass(3),
          new myClass(2),
      ]
      

      如果你不初始化你的类然后你想从myClass获取任何方法,你最终将对象转换为myClass

      【讨论】:

        【解决方案4】:

        类型 { aVariable: number; }myClass 不兼容

        正如the manual 所说,

        类中的私有成员和受保护成员会影响它们的兼容性。当检查类的实例的兼容性时,如果目标类型包含私有成员,则源类型也必须包含源自同一类的私有成员。同样,这同样适用于具有受保护成员的实例。这允许一个类与其超类的赋值兼容,但不能与来自不同继承层次结构的类兼容,否则它们具有相同的形状。

        如果myClass 应该被用作接口来分配结构上与myClass 类兼容的普通对象,则应提供单独的接口:

        interface IMyClass {
          aVariable: number;
        }
        
        export class myClass implements IMyClass {...}
        
        let someVar: IMyClass[] = [{
          aVariable: 3
        }];
        

        然后尝试初始化它

        应该注意,上面的代码没有初始化类。目前还不清楚分配普通对象而不是类实例的原因是什么,但如果someVar 应该包含myClass 的实例,则类型错误表明存在问题。应使用new 显式实例化实例:

        let someVar: myClass[] = [new myClass(3)];
        

        【讨论】:

          【解决方案5】:

          你忘记声明类了。你可以这样做

          const someVar: myClass[] = [new myClass(3), new myClass(2)];
          

          【讨论】:

            【解决方案6】:

            初始化这个类的正确方法是——

            export class myClass {
              constructor(public aVariable: number) {}
              private aPrivateVariable: number;
            }
            
            let someVar: myClass = new myClass(3);
            

            【讨论】:

              猜你喜欢
              • 2013-09-06
              • 2014-09-07
              • 2011-04-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-09-04
              相关资源
              最近更新 更多