Doubly Linked List With O(1) Removal

Implement a doubly linked list with O(1) push, unshift and known-node removal, iteration support and array conversion.

TypescriptData Integrity

Code

snippet
export interface ListNode<T> {
  value: T;
  prev: ListNode<T> | null;
  next: ListNode<T> | null;
}

export class DoublyLinkedList<T> implements Iterable<T> {
  private headNode: ListNode<T> | null = null;
  private tailNode: ListNode<T> | null = null;
  private count = 0;

  get length(): number {
    return this.count;
  }

  push(value: T): ListNode<T> {
    const node: ListNode<T> = { value, prev: this.tailNode, next: null };
    if (this.tailNode) this.tailNode.next = node;
    else this.headNode = node;
    this.tailNode = node;
    this.count += 1;
    return node;
  }

  unshift(value: T): ListNode<T> {
    const node: ListNode<T> = { value, prev: null, next: this.headNode };
    if (this.headNode) this.headNode.prev = node;
    else this.tailNode = node;
    this.headNode = node;
    this.count += 1;
    return node;
  }

  remove(node: ListNode<T>): boolean {
    if (node.prev === null && this.headNode !== node) return false;
    if (node.next === null && this.tailNode !== node) return false;
    if (node.prev) node.prev.next = node.next;
    else this.headNode = node.next;
    if (node.next) node.next.prev = node.prev;
    else this.tailNode = node.prev;
    node.prev = null;
    node.next = null;
    this.count -= 1;
    return true;
  }

  toArray(): T[] {
    const values: T[] = [];
    for (const value of this) values.push(value);
    return values;
  }

  *[Symbol.iterator](): IterableIterator<T> {
    let current = this.headNode;
    while (current) {
      yield current.value;
      current = current.next;
    }
  }
}