简体   繁体   中英

TS Error with Type Inference within Conditional Statement, when the condtional is using the result of a function call instead of a boolean expression

I have the following TypeScript class for a Linked List class, and everything works fine.

type ListItem = number | string | object;

class Node {
  private value: ListItem;
  private next: Node | null;

  constructor(value: ListItem) {
    this.value = value;
    this.next = null;
  }

  set nodeValue(value: ListItem) {
    this.value = value;
  }

  set nextNode(next: Node | null) {
    this.next = next;
  }

  get nodeValue(): ListItem {
    return this.value;
  }

  get nextNode(): Node | null {
    return this.next;
  }
}

export class LinkedList {
  private head: Node | null;
  private tail: Node | null;

  constructor(value: ListItem | null = null) {
    // Case 1: Linked List is initialised with 1 argument
    // Case 2: Linked List is initialised with null
    if (value) {
      const node = new Node(value);
      this.head = node;
      this.tail = node;
    } else {
      this.head = null;
      this.tail = null;
    }
  }

  public addLast(item: ListItem): void {
    const newNode = new Node(item);

    // Case 1 (if): Empty List
    // Case 2 (else): Non Empty List
    if (this.head === null || this.tail == null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.nextNode = newNode;
      this.tail = this.tail.nextNode;
    }
  }

  public addFirst(item: ListItem): void {
    const newNode = new Node(item);

    // Case 1 (if): Empty List
    // Case 2 (else): Non Empty List
    if (this.head === null || this.tail === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.nextNode = this.head;
      this.head = newNode;
    }
  }
}

Now I thought of creating a helper function, isEmpty(), to check if the Linked List is empty as shown below.

  private isEmpty(): boolean {
    return this.head === null || this.tail === null;
  }

And then changing the addLast() function as follows

  public addLast(item: ListItem): void {
    const newNode = new Node(item);

    // Case 1 (if): Empty List
    // Case 2 (else): Non Empty List
    if (this.isEmpty()) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.nextNode = newNode; // error
      this.tail = this.tail.nextNode; // error
    }
  }

But this causes an error, which makes sense because now I guess TS is not aware of the implementation of my conditional, only the result and does not know this.tail or this.head can no longer be null inside the else statement. Is there any way around this. Could I somehow use my helper without the tsc complaining. I thought of perhaps using a type guard of some sort but couldn't think of something. I am still new to TS, is this possible, am I missing something obvious I could do? Or is the helper not a feasible option?

You could use the not null or undefined assertion operator to let the compiler k now you know that tail is assigned at that point.

this.tail!.nextNode = newNode;
this.tail! = this.tail!.nextNode;

You can find out more here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM