Машинопись: использование Map<> с strictNullChecks

Учитывая следующий простой класс:

class Observer {
private subscribers: Map<string, Array<((data: any) => void)>> = new Map();     

public subscribe(event: string, callback: (data: any) => void) {
    if (!this.subscribers.has(event)) {
        this.subscribers.set(event, []);
    }

    this.subscribers.get(event).push(callback); //tsc says: Object is possibly 'undefined'
}

}

Кроме того, в tsconfig.json флаги strictNullChecks а также strict включены

Хотя subscribers проверяется наличие ключа текущего события, компилятор машинописного текста жалуется на сообщение об ошибке, показанное выше (this.subscribers.get(event) возможно не определено).

Если я не совсем неправ, this.subscribers.get(event) никогда не может быть undefined в этом случае.

Как я могу избавиться от этого сообщения?

2 ответа

Решение

Печатать Map прямо заявляет, что get может привести к undefined:

interface Map<K, V> {
    ...
    get(key: K): V | undefined;
    ...
}

Вот почему вы получаете сообщение об ошибке с параметром strictNullChecks.

Вы можете использовать оператор ненулевого утверждения, чтобы сообщить компилятору, что вы уверены, что он действительно имеет значение:

this.subscribers.get(event)!.push(callback);

Другой вариант (на мой взгляд, лучший) - это рефакторинг вашего кода следующим образом:

public subscribe(event: string, callback: (data: any) => void) {
    let callbacks = this.subscribers.get(event);
    if (!callbacks) {
        callbacks = []
        this.subscribers.set(event, callbacks);
    }

    callbacks.push(callback);
}

Почему бы не написать новый интерфейс/класс, который не допускал бы неопределенных значений?

      interface StrictMap<K, V> {
    ...
    get(key: K): V /* `| undefined` -> main diff. with `Map` native interface: The values can't be undefined */;
    ...
}

PS: На самом деле, я искал такой интерфейс/класс, когда нашел этот пост SO;)

Другие вопросы по тегам