我有以下代码:
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 个属性,智能感知可以提示您缺少属性。
现在,MyClass
实际上是一个类
,因此它不仅仅充当类型/接口(interface)。它还具有一些功能,即您可以调用构造函数,并且可以在声明类时使用 extends
。
现在,类的默认属性不是该类型的默认属性。如果您尝试在 typescript interface
或 type
中添加初始值设定项,您将看到错误;相反,当您向类添加默认属性时,这意味着实例仅在从构造函数调用时才会将该属性初始化为默认值。
因此,您可以采取一些措施来解决该问题:
- 在这种情况下,您可以继续使用
MyClass
作为类型,但您仍然需要在对象文字中声明name
属性:
let obj1: MyClass = {action: "act1", name: "first"};
如果你这样做,你仍然会面临:
Object literal may only specify known properties
因为MyClass
中不存在action
属性。您需要向 MyClass
添加一个 action
属性。
- 使用构造函数
let obj1 = new MyClass("act1");
虽然在某些情况下您可以有充分的理由使用类作为类型/接口(interface),但您可能应该在可能的情况下调用类构造函数(如本例所示),或者,正如注释所建议的那样,为此使用接口(interface)。
在这种情况下,我认为您应该更喜欢调用构造函数。
- 如果您只需要该类型来对变量类型进行编译器检查/智能感知,则可以使用接口(interface):
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
}
关于javascript - TypeScript:如何从对象初始化派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58525507/