繁体   English   中英

Typescript类成员未定义-编译器流程正确吗?

[英]Typescript class member undefined - Compiler Flow correct?

我刚接触打字稿,最近正在写一门课。 不幸的是,我的编辑器(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 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类的正确方法是什么?

this.foo不能是不确定的,并且如果流程正确或我错了,那么错误应该不会首先出现。

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

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

因此,请看一下您的代码段:

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键的值。

但是,打字稿无法知道这一点,因为一般而言,地图可能会为您尝试访问的任何键返回未定义的内容。 但是由于您作为开发人员更加了解,您可以使用非null断言! 使错误静音。

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
}

只需确保小心使用该运算符,因为您将覆盖打字稿试图提供的类型安全性。

通常,访问映射中某个键的值可能会返回未定义的值, 但是在您的特定情况下,我们可以看到这是不可能的 ,因为如果不存在,您会在此行上对其进行设置。 因此,在您的情况下,请使用! 操作员可能正是您需要的。

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

从以下位置更改您的返回语句: this.foo.length;

Number(!! this.foo && this.foo.length);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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