Использование карты ES6 с типом потока - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь обернуть голову вокруг потока, и я изо всех сил пытаюсь заставить его работать с ES6 Map

Рассмотрим этот простой случай ( live demo ):

// create a new map
const m = new Map();

m.set('value', 5);

console.log(m.get('value') * 5)

поток бросков:

console.log(m.get('value') * 5)
               ^ Cannot perform arithmetic operation because undefined [1] is not a number.
References:
[LIB] static/v0.72.0/flowlib/core.js:532:     get(key: K): V | void;
                                                               ^ [1]

Я тоже пробовал:

const m:Map<string, number> = new Map();

m.set('value', 5);

console.log(m.get('value') * 5)

Но я получил ту же ошибку

Я полагаю, что это потому, что flow думает, что значение также может быть чем-то иным, чем число, поэтому я попытался обернуть карту строгим установщиком и получателем ( live demo ):

type MyMapType = {
    set: (key: string, value: number) => MyMapType,
    get: (key: string) => number
};

function MyMap() : MyMapType {
    const map = new Map();

    return {
        set (key: string, value: number) {
          map.set(key, value);
          return this;
        },
        get (key: string) {
          return map.get(key);
        }
    }
}


const m = MyMap();

m.set('value', 5);

const n = m.get('value');

console.log(n * 2);

но потом я получил:

get (key: string) {
^ Cannot return object literal because undefined [1] is incompatible 
with number [2] in the return value of property `get`.
References:
[LIB] static/v0.72.0/flowlib/core.js:532:     get(key: K): V | void;
                                                               ^ [1]
get: (key: string) => number                            ^ [2]

Как мне сказать потоку, что я имею дело только с Картой чисел?

Edit:

Подход Typescript придает мне больше смысла, он добавляет set вместо get .

// TypeScript

const m:Map<string, number> = new Map();

m.set('value', 'no-number'); // << throws on set, not on get

console.log(m.get('value') * 2);

Есть ли способ заставить Flow вести себя так же?

1 Ответ

0 голосов
/ 15 мая 2018

Поток пытается сказать вам, что при вызове map.get(key), .get(...) может (V) или не может (void) вернуть что-то этой карты. Если ключ не найден на карте, то вызов .get(...) вернет undefined. Чтобы обойти это, вам нужно обработать случай, когда что-то возвращается неопределенным. Вот несколько способов сделать это:

( Попробуйте )

const m = new Map();

m.set('value', 5);

// Throw if a value is not found
const getOrThrow = (map, key) => {
  const val = map.get(key)
  if (val == null) {
    throw new Error("Uh-oh, key not found") 
  }
  return val
}

// Return a default value if the key is not found
const getOrDefault = (map, key, defaultValue) => {
  const val = map.get(key)
  return val == null ? defaultValue : val
}

console.log(getOrThrow(m, 'value') * 5)
console.log(getOrDefault(m, 'value', 1) * 5)

Причина, по которой map.get(key) напечатан как V | void, заключается в том, что карта может не содержать значение в этом ключе. Если у него нет значения в ключе, вы выдадите ошибку времени выполнения. Разработчики Flow решили, что они скорее заставят разработчика (вас и меня) подумать о проблеме, пока мы пишем код, а потом узнаем во время выполнения.

...