typescript类中的自引用数组
我试图用递归数组创建一个类层次结构,该数组本身引用它,但也正确地将类型分配给子类。 我想我很接近了,但是我得到了一个无法解释的typescript类中的自引用数组,typescript,Typescript,我试图用递归数组创建一个类层次结构,该数组本身引用它,但也正确地将类型分配给子类。 我想我很接近了,但是我得到了一个无法解释的TS2351错误 export interface ContentNodeJSON { id: string parentId?: string children: ContentNodeJSON[] } export class ContentNode { id: string parentId?: string children: this[
TS2351
错误
export interface ContentNodeJSON {
id: string
parentId?: string
children: ContentNodeJSON[]
}
export class ContentNode {
id: string
parentId?: string
children: this[]
constructor(model: ContentNodeJSON) {
this.id = model.id;
this.parentId = model.parentId;
this.children = model.children.map(child => new this(child));
}
}
错误如下:
This expression is not constructable.
Type 'ContentNode' has no construct signatures. TS2351
20 | this.parentId = model.parentId;
> 21 | this.children = model.children.map(child => new this(child));
| ^
22 | }
从构造函数本身调用构造函数是不可能的吗?我是否应该使用其他模式来实现此目标
编辑:
为了澄清我所说的“将类型正确分配给子类”的含义,如果我将子类定义为:
class Page extends ContentNode {}
然后Page。子项
的类型必须是Page
,而不是ContentNode
你可以在ContentNode.constructor中使用newcontentnode
,因为在后台它会编译成一个函数(或者更准确地说,它可以看作一个函数,但我离题了),所以它基本上是递归的,JS允许这样做
要回答您的编辑(这是边界a,但无论如何),您可以使用以下泛型类型:
export class ContentNode<T> {
id: string;
parentId?: string;
children: ContentNode<T>[];
constructor(model: ContentNodeJSON) {
this.id = model.id;
this.parentId = model.parentId;
this.children = model.children.map(child => new ContentNode(child));
}
}
导出类ContentNode{
id:字符串;
parentId?:字符串;
子节点:ContentNode[];
构造函数(模型:ContentNodeJSON){
this.id=model.id;
this.parentId=model.parentId;
this.children=model.children.map(child=>newcontentnode(child));
}
}
您想调用构造函数,因此它应该是this.constructor
,而不仅仅是this
。然而,Typescript似乎不喜欢这样,因为this.constructor
属于函数类型,而不是构造函数签名;我不知道为什么Typescript不知道构造函数是构造函数,但我们可以做一个类型断言,说我们知道它是:
const\u constructor=this.constructor as new(…args:any[])=>this;
this.children=model.children.map(child=>new_构造函数(child));
请注意,关于子对象有点可疑:这个[]
,因为如果obj
具有类型ContentNode
,那么您可以编写obj.children.push(newcontentnode(…)
),并且它将进行类型检查,即使运行时obj
可能是页面
实例。通过将其声明为只读子项:ReadonlyArray
,可以避免此问题
您也在约束子类,使其构造函数接受类型为ContentNodeJSON
的单个参数,但请注意,此约束在编译时不会被检查。您还有一个输入错误:id:string(
children:this[]
应该是children:ContentNode[]
请参见我在编辑中的评论,将儿童设置为ContentNode
是行不通的。我不认为这是一个变色龙问题;我从最初的措辞和多态这种类型的使用中理解了这一要求,我认为这种类型是有意的。我是typescript的新手,所以这种模式可能不是惯用的。它非常复杂在Swift中输入一个集合作为[Self]
和子类都将在运行时自动推断出正确的类型。我可以看出,当所有类型安全性在运行时消失时,它的价值可能会降低。我编辑过一篇文章,提到您可以声明只读子类:ReadonlyArray
作为该问题的解决方案。这并不是说数组实际上是不可变的,而是编译器er会检查你没有变异它。
export class ContentNode<T> {
id: string;
parentId?: string;
children: ContentNode<T>[];
constructor(model: ContentNodeJSON) {
this.id = model.id;
this.parentId = model.parentId;
this.children = model.children.map(child => new ContentNode(child));
}
}