Почему TypeScript показывает ошибку «Не удается вызвать объект, который, возможно, является undefined'.ts (2722)» после необязательного оператора цепочки? - PullRequest
0 голосов
/ 05 апреля 2020

В течение этого периода пребывания я решил погрузиться в TypeScript и начал практиковать его, реализовав некоторые базовые c структуры данных. Я пытаюсь реализовать пользовательский стек, который использует пользовательские узлы.

Мои стековые узлы определены следующим образом:

class StackNode {

  private val: any;
  private nxt: StackNode | undefined = undefined;

  constructor(val: any, nxt?: StackNode | undefined) {
    this.val = val;
    this.nxt = nxt || undefined;
  }

  get value(): any {
    return this.value;
  }

  get next(): StackNode | undefined {
    return this.next;
  }

}

export default StackNode;


И фактический стек:

class Stack {

  private capacity!: number;
  private top?: StackNode | undefined = undefined;
  private size: number = 0;

  constructor(capacity: number, initialValues?: Array<any>) {
    this.capacity = capacity;

    if (initialValues) {
      this.size = initialValues.length;
      this.top = this._initStack(initialValues, initialValues.length - 1);
    }

  };

  private _initStack = (array: Array<any>, idx: number): StackNode => {
    if (idx == 0) {
      return new StackNode(array[idx], undefined);
    } else {
      return new StackNode(array[idx], this._initStack(array, idx-1));
    }
  }

  pop(): any {
    const value = this.top?.value();
    this.top = this.top?.next();
    return value;
  }

}

export default Stack;

проблема здесь в строке с необязательным оператором сцепления в pop-методе this.top = this.top?.next()

Я понял, что выражение this.top?.next() должно быть эквивалентно

(this.top === null || this.top === undefined)? undefined : this.top.next()

но я все еще получаю ошибку

Невозможно вызвать объект, который, возможно, равен undefined.ts (2722)

, когда вызов сделан, хотя на этом этапе он больше не должен быть неопределенным.

Почему это так? Что мне здесь не хватает? И StackNode.nxt, и Stack.top могут быть неопределенными. Я пытался сделать это по-старому, как это:

if (this.top !== null || this.top !== undefined) {
  const value = this.top.value()
  this.top = this.top.next()
}

Но я все еще получаю ту же ошибку, хотя здесь должно быть уверен, что this.top не может быть неопределенным, но должен быть или, по крайней мере, должно быть, типа StackNode.

Как это должно работать, чтобы при извлечении из пустого стека метод pop возвращал undefined, а при извлечении последнего элемента его следующий, который не определен, равен установить в качестве вершины стека.

Я использую TS 3.8.3

1 Ответ

1 голос
/ 05 апреля 2020

Вы определяете следующее как получатель, поэтому к нему нужно обращаться следующим образом: this.top = this.top?.next

Единственная причина, по которой const value = this.top?.value(); даже компилируется, состоит в том, что вы используете 'any' (НЕ ДЕЛАЙТЕ ЭТО, КОГДА-ЛИБО! !), а машинопись предполагает, что get value может возвращать функцию, которую вы вызываете.

Вы должны определить StackNode, используя обобщенные значения. Например,

class StackNode<T> {

  private val: T;
  private nxt: StackNode<T> | undefined = undefined;

  constructor(val: T, nxt?: StackNode<T> | undefined) {
    this.val = val;
    this.nxt = nxt || undefined;
  }

  get value(): T {
    return this.value;
  }

  get next(): StackNode<T> {
    return this.next;
  }

}


class Stack<T> {

  private capacity!: number;
  private top?: StackNode<T> | undefined = undefined;
  private size: number = 0;

  constructor(capacity: number, initialValues?: Array<any>) {
    this.capacity = capacity;

    if (initialValues) {
      this.size = initialValues.length;
      this.top = this._initStack(initialValues, initialValues.length - 1);
    }

  };

  private _initStack = (array: Array<any>, idx: number): StackNode<T> => {
    if (idx == 0) {
      return new StackNode(array[idx], undefined);
    } else {
      return new StackNode(array[idx], this._initStack(array, idx-1));
    }
  }

  pop(): T | undefined {
    const value = this.top?.value(); //doesn't compile
    this.top = this.top?.next(); //doesn't compile either
    return value;
  }

}

Тогда const value = this.top?.value(); также не скомпилируется.

...