为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 TypeScript 在可选链接运算符之后显示“无法调用可能是'未定义'.ts

为什么 TypeScript 在可选链接运算符之后显示“无法调用可能是'未定义'.ts

慕后森 2022-06-16 14:39:44
在这段居家期间,我决定深入研究 TypeScript,并开始通过实现一些基本的数据结构来实践它。我正在尝试实现一个使用自定义节点的自定义堆栈。我的 StackNode 定义如下: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-method 中可选链接运算符的行this.top = this.top?.next()我的理解是表达式this.top?.next()应该等同于(this.top === null || this.top === undefined)? undefined : this.top.next()但我仍然收到错误无法调用可能是“未定义”的对象。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 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

您将 next 定义为 getter,因此必须像这样访问它:this.top = this.top?.next


甚至编译的唯一原因const value = this.top?.value();是因为您使用“任何”(不要这样做,永远!!),并且打字稿假定这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();也不会编译。


查看完整回答
反对 回复 2022-06-16
  • 1 回答
  • 0 关注
  • 136 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号