如果省略,TypeScript类可选属性可能会回退到默认值吗?

时间:2017-04-08 15:11:38

标签: typescript default

如果用户省略了类成员属性默认值,有没有办法分配它?

我有一个自定义类,它构成另一个类的可选实例:

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 -variable中删除可选符号,但这会产生编译错误,因为该对象必须与 MyClass1 的结构相匹配。我想我通过强制转换设法编译没有错误,但它没有解决问题(虽然我不确定这是否正确编译):

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

在两种情况下 classInstance 都没有得到构造函数设置的默认值,它出现了null / undefined。

对我而言,无论如何解决铸造问题(无论是设置属性可选还是使用铸造)都是无关紧要的,只要我可以控制默认值。

1 个答案:

答案 0 :(得分:1)

这里的问题是

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

这里是不是 MyClass1实例。 TypeScript类型系统被“欺骗”认为普通对象是MyClass1实例。

它将被转换为var myNewClass = { name: "MyClass" }MyClass1类未实例化。故事的结尾。

执行预期操作的正确方法是提供从JSON到类构造函数的值。考虑到对象属性(classInstance)可以是undefined,类属性不能依赖于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"
});

当提供和处理数据时,如何考虑类的使用(即,仅对未定义的值使用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
});