简体   繁体   English

带有私有变量的TypeScript类声明错误

[英]TypeScript class declaration error with private variable

If I have a TypeScript class declaration like this: 如果我有这样的TypeScript类声明:

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

and then try to initialize it with: 然后尝试使用以下方法初始化它:

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

I get an error (at least in VS Code) saying: 我收到一个错误(至少在VS Code中),说:

Property 'aPrivateVariable' is missing in type '{ aVariable: number; 类型'{avariable:number;类型中缺少属性'aPrivateVariable' }'. }”。

Why can't I do this? 我为什么不能这样做?

Thanks. 谢谢。

Imagine your class also has a method that uses this field: 想象一下,您的类也有使用此字段的方法:

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

Now if you would do the following: 现在,如果您要执行以下操作:

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

 instance.test();

It would fail. 它会失败。 Therefore, you also need to add private properties. 因此,您还需要添加私有属性。

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

Type { aVariable: number; } 输入{ aVariable: number; } { aVariable: number; } isn't compatible with myClass { aVariable: number; }myClass不兼容

As the manual states, 手册所述,

Private and protected members in a class affect their compatibility. 类中的私有成员和受保护成员会影响其兼容性。 When an instance of a class is checked for compatibility, if the target type contains a private member, then the source type must also contain a private member that originated from the same class. 当检查一个类的实例的兼容性时,如果目标类型包含一个私有成员,那么源类型还必须包含一个源自同一类的私有成员。 Likewise, the same applies for an instance with a protected member. 同样,对于具有受保护成员的实例也是如此。 This allows a class to be assignment compatible with its super class, but not with classes from a different inheritance hierarchy which otherwise have the same shape. 这样一来,一个类就可以与其父类兼容,但不能与其他继承层次结构相同的类的继承兼容。

If myClass is supposed to be used as interface to assign plain objects that are structurally compatible with myClass class, separate interface should be provided: 如果应该将myClass 用作分配与myClass类在结构上兼容的普通对象的接口,则应提供单独的接口:

interface IMyClass {
  aVariable: number;
}

export class myClass implements IMyClass {...}

let someVar: IMyClass[] = [{
  aVariable: 3
}];

and then try to initialize it 然后尝试初始化它

It should be noticed that the code above doesn't initialize the class. 应该注意的是,上面的代码并未初始化该类。 It's unclear what were the reasons to assign plain objects instead of class instances, but if someVar should contain instances of myClass , type error indicates the problem. 目前尚不清楚分配普通对象而不是类实例的原因是什么,但是如果someVar应该包含myClass实例,则类型错误指示问题。 Instances should be explicitly instantiated with new : 实例应使用new显式实例化:

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

Defining the objects in the way you did ( { aVariable: 2} ) does not instantiate them as myClass objects. 以您的方式定义对象( { aVariable: 2} )不会将它们实例化为myClass对象。 This is a problem since aPrivateVariable is not being instantiated because myClass constructor is never called and the object you add does not match what myClass contains. 这是一个问题,因为未实例化aPrivateVariable因为从不调用myClass构造函数,并且您添加的对象与myClass包含的内容不匹配。

As this excerpt from the typescript handbook on type compatibility states : 正如摘录自打字机手册中关于类型兼容性的陈述

Private and protected members in a class affect their compatibility. 类中的私有成员和受保护成员会影响其兼容性。 When an instance of a class is checked for compatibility, if the target type contains a private member, then the source type must also contain a private member that originated from the same class. 当检查一个类的实例的兼容性时,如果目标类型包含一个私有成员,那么源类型还必须包含一个源自同一类的私有成员。 Likewise, the same applies for an instance with a protected member. 同样,对于具有受保护成员的实例也是如此。 This allows a class to be assignment compatible with its super class, but not with classes from a different inheritance hierarchy which otherwise have the same shape. 这样一来,一个类就可以与其父类兼容,但不能与其他继承层次结构相同的类的继承兼容。

One way to deal with this is to instantiate every object using something such as map() 一种解决方法是使用诸如map()类的方法实例化每个对象。

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

Or, if you're confident of the shape of the object, you can use type coercion: 或者,如果您对对象的形状有信心,则可以使用强制类型:

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

Be careful with this approach though since it does not guarantee that what's contained in the array matches the model of the class. 但是请谨慎使用此方法,因为它不能保证数组中包含的内容与类的模型匹配。

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

The correct way would be really initializing your class like this: 正确的方法是像这样真正初始化您的类:

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

If you don't initialize your class then you want to get any methods from myClass , you will end up with object cast as myClass . 如果不初始化类,那么您想从myClass获取任何方法,最终将对象转换为myClass

You forgot to declare the class. 您忘了宣布课了。 You can do it like this 你可以这样

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

Correct way to initialize this class is - 初始化此类的正确方法是-

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

let someVar: myClass = new myClass(3);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM