【问题标题】:Typescript class member undefined - Compiler Flow correct?打字稿类成员未定义 - 编译器流程正确吗?
【发布时间】:2018-01-08 23:10:52
【问题描述】:

我是打字稿的新手,最近正在写一门课。不幸的是,我的编辑器(Visual Studio Code)因为我无法理解的错误而困扰我。它说:“对象(foo)可能未定义”。但是怎么做?

这是一个例子:

export class Foo {
    foo: string | undefined;
    constructor() {
        this.foo = "hello";
    }

    lengthOfFoo() {
        /*if (!this.foo) {
            return;
        }*/
        let len = this.foo.length; // <- error: the object (foo) is possible undefined
        return len;
    }
}

如果我取消注释上面的检查,错误才会消失,但由于构造函数:

constructor() {
    this.foo = "hello";
}

this.foo 不能是未定义的,如果流程正确或我错了,则不应首先出现错误?

为了解释我为什么使用这个表达式

foo: string | undefined;

这只是一个简化的例子。我实际上是在尝试使用具有可以未定义的 Map.get() 函数的 Map 类型。这里是 Map Type 的声明:

interface Map<K, V> {
    clear(): void;
    delete(key: K): boolean;
    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
    get(key: K): V | undefined;
    has(key: K): boolean;
    set(key: K, value: V): this;
    readonly size: number;
}

这里是实际代码:

export default class EventEmitter {
    listener: Map<string, Function[]> = new Map();
    foo: string | undefined = "hello";

    constructor() {
        this.listener = new Map();
        this.foo = "hello";

    }

    addListener(label: string, callback: Function) {
        this.listener.has(label) || this.listener.set(label, []);
        this.listener.get(label).push(callback); <- error: object is possible undefined
        this.foo.length; // <- error: object is possible undefined
    }

    removeListener(label: string, callback: Function) {

    }

    emit(label: string, ...args: any[]) {

    }
}

谁能向我解释为什么会发生这个错误以及实现 EventEmitter 类的正确方法是什么?

【问题讨论】:

    标签: javascript class typescript ecmascript-6


    【解决方案1】:

    this.foo 不能是未定义的,如果流程正确或我错了,则不应首先出现错误?

    肯定错了。有人可以这样写:

    const f = new Foo();
    f.foo = undefined;
    f.lengthOfFoo();
    

    【讨论】:

      【解决方案2】:

      所以看看你的sn-p:

      addListener(label: string, callback: Function) {
          this.listener.has(label) || this.listener.set(label, []);
          this.listener.get(label).push(callback); // <- error: object is possible undefined
          this.foo.length; // <- error: object is possible undefined
      }
      

      如果您尝试从地图中获取的键不存在,您会立即将其设置为空数组。所以你正确推断出下一行的键值不能是undefined

      但是打字稿无法知道这一点,因为通常地图可以为您尝试访问的任何键返回未定义。但是,作为开发人员,您知道得更清楚,您可以使用非空断言! 来消除错误。

      addListener(label: string, callback: Function) {
          this.listener.has(label) || this.listener.set(label, []);
          this.listener.get(label)!.push(callback); // <- note the ! after get call
          this.foo.length; // <- error: object is possible undefined
      }
      

      请务必小心使用该运算符,因为您正在覆盖 typescript 试图提供的类型安全性。

      一般来说,访问映射中某个键的值可能会返回未定义,但在您的具体情况下,我们可以看到这是不可能的,因为我们看到您在此之前设置了它如果它不存在。因此,在您的情况下,使用 ! 运算符可能正是您所需要的。

      【讨论】:

      • 感谢您的解释。似乎是一个非常优雅的解决方案。
      【解决方案3】:

      要添加到 Rayans 的回复中,以解决此问题:

      将您的退货声明从: this.foo.length;

      数字(!!this.foo && this.foo.length);

      【讨论】:

        猜你喜欢
        • 2022-11-15
        • 2013-06-13
        • 2017-05-09
        • 2020-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-16
        相关资源
        最近更新 更多