我有以下代码:
class MyClass {
name: string = "myname";
constructor(public action: string) { }
}
let obj1: MyClass = { action: "act1" };
它不可编译。最后一行的错误是:
Property 'name' is missing in type '{ action: string; }' but required in type 'MyClass'.
我本来以为,因为"name"属性有一个默认值,所以不应该为obj1指定它。但事实并非如此。此外,最后一行似乎甚至没有调用ctor,所以它不是一个ctor语法糖,而是一个完全不同的初始化调用。有没有一种方法可以设置某些属性的默认值,并避免在这种技术中初始化它们?
编写时:
let obj1: MyClass = { action: "act1" };
您使用类MyClass
作为类型,这意味着您告诉编译器变量obj1
符合MyClass
类型。它必须具有类的所有必填字段,并且不能具有任何未知的属性。
这很好,因为如果类型有200个属性,intellisense可以提示您缺少属性。
现在,MyClass
实际上是class
,所以它不仅仅作为类型/接口工作。它还有一些功能,即您可以调用构造函数,并且在声明类时可以使用extends
。
现在,类的默认属性不是该类型的默认属性。如果您尝试在类型脚本interface
或type
中添加初始值设定项,您将看到一个错误;相反,当您向类添加默认属性时,这意味着只有从构造函数调用时,实例才会将该属性初始化为默认值。
所以,你可以做一些事情来解决这个问题:
- 在该场景中,您可以继续使用
MyClass
作为类型,但仍需要在对象文字中声明name
道具:
let obj1: MyClass = {action: "act1", name: "first"};
如果你这样做,你仍然会面临一个:
对象文字只能指定已知属性
因为action
属性在MyClass
中不存在。您需要将action
属性添加到MyClass
中。
- 使用构造函数
let obj1 = new MyClass("act1");
虽然在某些情况下,您可以有正当理由将类用作类型/接口,但您可能应该在可能的情况下调用类构造函数(如本例所示(,或者,正如注释所建议的那样,为此使用接口。
在这种情况下,我认为您应该更喜欢调用构造函数。
- 如果您只需要该类型来对变量类型进行编译器检查/intellisense,则可以使用接口:
interface MyCustomType {
name: string;
action?: string;
}
因此,如果您尝试将一个不带名称的变量键入为MyCustomType
,则会收到警告:
let obj: MyCustomType = {
action: 'act1',
} // error, you need to set 'name' since it is a mandatory field
您可以设置有操作或无操作的对象,因为它是可选的(由于声明中的"?"(。
无法添加未知字段:
let obj: MyCustomType = {
name: 'name',
value: 1, // error, unknown field
}
在您的代码let obj1: MyClass = { action: "act1" };
中
您并没有将obj1
初始化为MyClass
的实例,而是将对象{ action: "act1" }
分配给一个假定类型为MyClass
的变量。因此出现了打字错误。
正确实施:
class MyClass {
name: string = "myname";
constructor(public action: string) {
}
}
let obj1 = new MyClass("action");
console.log(obj1);
/*
outputs:
{
action: "action"
name: "myname"
}
*/
感谢上面的所有建议,我终于想出了一个解决方案,让我使用ctor,但仍然会得到任何丢失/多余值的错误,并让我在对象文字"initializer"中设置可选的默认值:
class MyClassValues {
constructor(public name: string, public action?: string) {}
}
class MyClass extends MyClassValues {
constructor(v: MyClassValues) {
super(v.name, "default1");
}
}
let c1 : MyClass = new MyClass({}); // error, missing name
let c2 : MyClass = new MyClass({x:"y"}); // error, unknown prop
let c3 : MyClass = new MyClass({name:"hello"}); // no error
console.log(c3.action); // prints "default1";