Typescript 类型脚本、字段初始值设定项和派生类
我正在用Typescript创建一个父类和子类。每个字段定义了一些字段属性。我试图保持代码干净,使用构造函数的Partial方法。但我不知道如何在超级调用中将父对象的属性传递给父对象,并在Object.assign中仅使用子对象的唯一道具初始化子对象的道具-如果这是正确的范例的话。以下是我所拥有的:Typescript 类型脚本、字段初始值设定项和派生类,typescript,Typescript,我正在用Typescript创建一个父类和子类。每个字段定义了一些字段属性。我试图保持代码干净,使用构造函数的Partial方法。但我不知道如何在超级调用中将父对象的属性传递给父对象,并在Object.assign中仅使用子对象的唯一道具初始化子对象的道具-如果这是正确的范例的话。以下是我所拥有的: export class Parent { name: string = '' durationInSec: number = 0.0 optionalField?: string;
export class Parent {
name: string = ''
durationInSec: number = 0.0
optionalField?: string;
constructor(init: Partial<Parent>) {
Object.assign(this, init)
}
}
export enum Types { A, B, C }
export class ChildA extends Parent {
kind = Types.A
childRequired1: string = '' // ??? have to set defaults for all props with this technique
childOption1?: string
constructor(init: Partial<ChildA>) {
super(init) // ??? wrong, passes too many things to super
Object.assign(this, init) // this would be fine alone, but tsc says need to call super()
}
}
// similar for ChildB, ChildC etc.
let obj1 = new ChildA({name: 'foo', childRequired1: 'bar'})
这在Typescript中是一个好的范例吗?有更好的方法吗?问题是init是部分的,所以如果您不为childRequired1声明默认值,那么就没有什么可以阻止某人执行新的ChildA{}事实上,Parent.durationnsec实际上不是Parent的可选选项,但您依赖于默认值
问题的第二部分是,似乎使用Object.assignthis。。。在构造函数中,似乎不满足初始化构造函数中所有必需参数的要求。关于这件事,似乎有一个很好的解释
在我看来,你有两个选择:
在所有必需的类型中设置默认值,以确保它们始终具有值,并且仍然可以使用Partial
要详细得多:
我很害怕。重复太多了!每个字段名必须键入三次。也许使用构造函数参数属性更好?这似乎不太酷,因为您没有更容易地扩展好的命名参数,顺序不重要,等等。。还有,在每个派生类的超级调用和构造函数参数列表中,您必须重复所有基类的成员,所以这甚至不是更好。您还可以使用childRequired1!之类的工具来完成一些骇客操作:字符串,使TypeScript认为它总是有一个值。然而,如果你忘记提供一个值,你会失去任何形式的理智检查???必须使用此技术为所有道具设置默认值。。。替代方案是什么?如果你需要道具,你需要在某个地方设置默认值,对吗?还是我遗漏了什么?另外,为什么不在子类中调用super{},然后执行Object.assignthis,init之后呢?我希望父类的一些字段是必需的,一些是可选的,并且是相同的w/child。使用这种方法,我似乎必须为必填字段设置默认值,因为部分字段是必需的,所以它们实际上不是必需的。
export class Parent {
name: string;
durationInSec: number;
optionalField?: string;
constructor(init: Parent) {
this.name = init.name;
this.durationInSec = init.durationInSec;
this.optionalField = init.optionalField;
}
}
export enum Types { A, B, C }
export class ChildA extends Parent {
kind: Types;
childRequired1: string;
childOption1?: string;
constructor(init: ChildA) {
super(init as Parent) // Downcasted, it should be ok.
this.kind = init.kind;
this.childRequired1 = init.childRequired1;
this.childOption1 = init.childOption1;
}
}
let obj1 = new ChildA({
name: 'foo',
childRequired1: 'bar',
durationInSec: 1,
kind: Types.A
});