typescript - TypeScript:在嵌套的静态类中强制执行泛型类型约束
问题描述
作为示例,考虑 TypeScript 3.7.5 中的最小链表类。ALinkedList<T>
由 的链组成ListNode<T>
,其中类型变量T
在两者中引用相同的类型。还假设您正在使用一个私有静态字段LinkedList
来隐藏ListNode
,因为它是一个不相关的实现细节。
class LinkedList<T> {
private head: ??? = null;
private tail: ??? = null;
private static ListNode = class ListNode<T> {
constructor(
public val: T | null,
public next: ListNode<T> | 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 || this.head.val === null) {
throw Error();
} else {
const t = this.head.val;
this.head = this.head.next;
return t;
}
}
}
我如何表示???
上面的类型?不是List.ListNode
或List.ListNode<T>
。这不是有效的 TypeScript(至少从 3.7.5 开始)。它也不是InstanceType<typeof List.ListNode>
。这是一个有效的类型,但它失去了泛型参数T
,因此无法强制执行封闭类和嵌套类由相同类型参数化的约束。
现在我们通过引入一个 dummyhead
并依靠类型推断来修改类:
class LinkedList<T> {
private head = LinkedList.makeNode<T>();
private tail = this.head.next;
private static makeNode<T>() {
return new this.ListNode<T>(null, null);
}
private static ListNode = class ListNode<T> {
constructor(
public val: T | null,
public next: ListNode<T> | null) {}
};
append(item: T): this {
if (!this.tail) {
this.head.next = {val: item, next: null};
this.tail = this.head.next;
} else {
this.tail.next = {val: item, next: null};
this.tail = this.tail.next;
}
return this;
};
remove(): T {
if (!this.head.next || this.head.next.val === null) {
throw Error();
} else {
const t = this.head.next.val;
this.head.next = this.head.next.next;
return t;
}
}
}
给定这段代码,TypeScript 可以证明它remove()
确实返回了T
. 在悬停时,VSC 建议类型head
为ListNode<T>
. 如何明确表达这种类型?
解决方案
创建一个字段来存储列表节点的类型对我来说没有意义。它也不需要是一个类;对象类型很好。我会这样做:[ts 操场]
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;
}
}
}
推荐阅读
- flutter - 是否有任何资源可以解释每个 Flutter TextTheme 值的影响?
- html - HTML Bootstrap Carousel(轮播控件)
- windows - GetStringType 如何导致 Dll Main 死锁?
- sqlite - 使用 SQL 对日期进行排序
- git - 在git上将分支与主分支合并后无法将合并推送到服务器
- dart - 如何在 Aqueduct Dart 服务器中获取客户端请求的 IP 地址
- r - 创建一个可以接受数据集和对象名称以及这些名称作为字符串对象的 R 函数
- sql - ORACLE中WHERE中的(+)是什么意思
- postgresql - 如何在 ARRAY_AGG() 中使用 DISTINCT ON?
- python - Python - 使用 Osmnx 包获取“TypeError:'CRS' 类型的参数不可迭代”