TypeScript:在嵌套的静态类中强制执行泛型类型约束 以示例为例,在TyrScript 3.7.5中考虑最小链接列表类。LinkedList由一系列的ListNode组成,其中类型变量T在这两个列表中引用相同的类型。另外,假设您正在使用LinkedList中的私有静态字段来隐藏ListNode,因为它是一个不相关的实现细节 类链接列表{ 私有头:???=null; 私有尾部:???=null; 私有静态ListNode=类ListNode{ 建造师( 公共值:T | null, 公共下一个:ListNode | null){} }; 追加(项目:T):此{ 如果(!this.tail){ this.tail={val:item,next:null}; this.head=this.tail; }否则{ this.tail.next={val:item,next:null}; this.tail=this.tail.next; } 归还这个; }; 删除():T{ 如果(!this.head | | this.head.val==null){ 抛出错误(); }否则{ const t=this.head.val; this.head=this.head.next; 返回t; } } }

TypeScript:在嵌套的静态类中强制执行泛型类型约束 以示例为例,在TyrScript 3.7.5中考虑最小链接列表类。LinkedList由一系列的ListNode组成,其中类型变量T在这两个列表中引用相同的类型。另外,假设您正在使用LinkedList中的私有静态字段来隐藏ListNode,因为它是一个不相关的实现细节 类链接列表{ 私有头:???=null; 私有尾部:???=null; 私有静态ListNode=类ListNode{ 建造师( 公共值:T | null, 公共下一个:ListNode | null){} }; 追加(项目:T):此{ 如果(!this.tail){ this.tail={val:item,next:null}; this.head=this.tail; }否则{ this.tail.next={val:item,next:null}; this.tail=this.tail.next; } 归还这个; }; 删除():T{ 如果(!this.head | | this.head.val==null){ 抛出错误(); }否则{ const t=this.head.val; this.head=this.head.next; 返回t; } } },typescript,types,Typescript,Types,如何表示上面的类型??它不是List.ListNode或List.ListNode。这不是有效的TypeScript(至少从3.7.5开始)。它也不是InstanceType。这是一个有效的类型,但它会丢失泛型参数T,因此无法强制执行封闭类和嵌套类由同一类型参数化的约束 现在,我们通过引入一个虚拟的头并依靠类型推断来修改类: 类链接列表{ private head=LinkedList.makeNode(); private tail=this.head.next; 私有静态makeNode()

如何表示上面的类型
?它不是
List.ListNode
List.ListNode
。这不是有效的TypeScript(至少从3.7.5开始)。它也不是
InstanceType
。这是一个有效的类型,但它会丢失泛型参数
T
,因此无法强制执行封闭类和嵌套类由同一类型参数化的约束

现在,我们通过引入一个虚拟的
并依靠类型推断来修改类:

类链接列表{
private head=LinkedList.makeNode();
private tail=this.head.next;
私有静态makeNode(){
返回新的this.ListNode(null,null);
}
私有静态ListNode=类ListNode{
建造师(
公共值:T | null,
公共下一个:ListNode | null){}
};
追加(项目:T):此{
如果(!this.tail){
this.head.next={val:item,next:null};
this.tail=this.head.next;
}否则{
this.tail.next={val:item,next:null};
this.tail=this.tail.next;
}
归还这个;
};
删除():T{
如果(!this.head.next | this.head.next.val==null){
抛出错误();
}否则{
const t=this.head.next.val;
this.head.next=this.head.next.next;
返回t;
}
}
}

给定这段代码,TypeScript可以证明
remove()
实际上返回
T
的实例。悬停在上方时,VSC建议
头的类型为
ListNode
。如何显式表示此类型?

创建一个字段来存储列表节点的类型对我来说没有意义。它也不一定是一门课;对象类型很好。我会这样做:

类型ListNode={
val:T;
下一步:ListNode | null;
};
类链接列表{
私有头:ListNode | null=null;
私有尾部:ListNode | null=null;
追加(项目:T):此{
如果(!this.tail){
this.tail={val:item,next:null};
this.head=this.tail;
}否则{
this.tail.next={val:item,next:null};
this.tail=this.tail.next;
}
归还这个;
};
删除():T{
如果(!this.head){
抛出错误();
}否则{
const t=this.head.val;
this.head=this.head.next;
返回t;
}
}
}

创建一个字段来存储列表节点的类型对我来说没有意义。它也不一定是一门课;对象类型很好。我会这样做:

类型ListNode={
val:T;
下一步:ListNode | null;
};
类链接列表{
私有头:ListNode | null=null;
私有尾部:ListNode | null=null;
追加(项目:T):此{
如果(!this.tail){
this.tail={val:item,next:null};
this.head=this.tail;
}否则{
this.tail.next={val:item,next:null};
this.tail=this.tail.next;
}
归还这个;
};
删除():T{
如果(!this.head){
抛出错误();
}否则{
const t=this.head.val;
this.head=this.head.next;
返回t;
}
}
}

LinkedList中嵌套ListNode的目的是什么?这条线试图实现什么:<代码>私有静态列表节点=类ListNoel{{} /代码>。请考虑将上面的代码转换成一个可以被放入独立IDE中以演示您的问题的代码。任何与您的问题无关的问题都应该消除(例如,
List
未声明,
ListNode
的属性未初始化),以便回答问题的人能够专注于正确的事情。祝你好运在LinkedList中嵌套ListNode的目的是什么?这条线试图实现什么:<代码>私有静态列表节点=类ListNoel{{} /代码>。请考虑将上面的代码转换成一个可以被放入独立IDE中以演示您的问题的代码。任何与您的问题无关的问题都应该消除(例如,
List
未声明,
ListNode
的属性未初始化),以便回答问题的人能够专注于正确的事情。祝你好运谢谢你的建议!我感兴趣的不是如何写清单。我特别感兴趣的是如何访问嵌套在静态字段中的泛型类的类型。考虑到在第二个代码段中,tsc似乎能够对
头的类型进行推理,如果这种类型在TS中无法表达,那将非常奇怪。你不同意吗?嗯,你甚至可以表达ListNode本身的类型吗?这里将显示什么:
静态列表节点:??=类…
首先,我对这种嵌套的意义/意图感到困惑。是的,这几乎是相同的问题。很明显,这是一个类型化表达式,编译器可以对它的类型进行推理。我认为不是很好:),但足够清楚地知道
remove()
返回一个

type ListNode<T> = {
  val: T;
  next: ListNode<T> | null;
};

class LinkedList<T> {
  private head: ListNode<T> | null = null;
  private tail: ListNode<T> | null = null;


  append(item: T): this {
    if (!this.tail) {
      this.tail = {val: item, next: null};
      this.head = this.tail;
    } else {
      this.tail.next = {val: item, next: null};
      this.tail = this.tail.next;
    }
    return this;
  };

  remove(): T {
    if (!this.head) {
      throw Error();
    } else {
      const t = this.head.val;
      this.head = this.head.next;
      return t;
    }
  }
}