如果省略,TypeScript class 可选属性是否可以回退到默认值?

Possible to have TypeScript class optional properties fall back to default value if omitted?

如果 class 成员属性被用户省略,是否有任何方法可以分配默认值?

我有一个自定义 class,其中包含另一个 class:

的可选实例
export class MyClass1 {
    constructor() {
        this.name = "";
        this.classInstance = new MyClass2();
    }
    name: string;           // name of the object
    classInstance?: MyClass2;
}

class MyClass2 {
    constructor() {
        this.name = "MyClass2 initial name";
    }

    name: string;
}

MyClass1的内容来自JSON,所以有些时候成员变量classInstance可以未定义。在这些情况下,我希望 MyClass1 构造函数将 new MyClass2() 初始化为 classInstance成员变量.

这就是我分配创建 MyClass1 实例的方式:

let myNewClass: MyClass1 = {
    name: "MyClass"
}

因为 classInstance 被省略了,我假设它会在构造函数中设置默认值。然而,这种情况并非如此。我还尝试从 classInstance 变量中删除可选符号,但这会产生编译错误,因为对象必须匹配 MyClass1 的结构。我想我通过强制转换设法没有错误地编译,但它没有解决问题(虽然我也不确定是否编译正确):

let myNewClass: MyClass1 = {
    name: "MyClass"
} as MyClass1

在这两种情况下,classInstance 都没有得到构造函数设置的默认值,结果是 null/undefined.

对我来说,转换问题如何解决(是设置可选属性还是使用转换)并不重要,只要我能控制默认值即可。

这里的问题是

let myNewClass: MyClass1 = {
    name: "MyClass"
} as MyClass1

这里是不是MyClass1实例。 TypeScript 类型系统 'cheated' 认为普通对象是 MyClass1 实例。

它将被转译为 var myNewClass = { name: "MyClass" }MyClass1 class 未实例化。故事结束。

做预期事情的正确方法是提供从 JSON 到 class 构造函数的值。考虑到对象属性 (classInstance) 可以是 undefined,class 属性不能依赖像 constructor({ classInstance = new MyClass2 }) { ... } 这样的默认值,应该手动分配:

export class MyClass1 {
    constructor(jsonMyClass1: MyClass1 = {}) {
        const { name, classInstance } = jsonMyClass1;
        this.name = 'name' in jsonMyClass1 ? name : "";
        this.classInstance = 'classInstance' in jsonMyClass1 ? classInstance : new MyClass2;
    }
    name: string;
    classInstance?: MyClass2;
}

let myNewClass: MyClass1 = new MyClass1({
    name: "MyClass"
});

当数据被提供和处理时考虑到 classes 将如何使用它(即使用 null 专门用于未定义的值),配方可以修改为使用语言提供的权力:

export class MyClass1 {
  constructor(jsonMyClass1: MyClass1 = {} as MyClass1) {
        const { name = "", classInstance = new MyClass2 } = jsonMyClass1;
        this.name = name;
        this.classInstance = classInstance;
    }
    name: string;
    classInstance: MyClass2;
}

let myNewClass: MyClass1 = new MyClass1({
    name: "MyClass",
    classInstance: null
});