作为示例,考虑 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>. 如何明确表达这种类型?