Lodash Flow и TypeScript - PullRequest
       23

Lodash Flow и TypeScript

12 голосов
/ 21 июня 2019

Я следил за статьей о Lodash, Почему использование _.chain является ошибкой , и это подчеркивает, что вы можете устранить необходимость в цепочке, используя Flow.

В приведенном примере используется цепочка

import _ from "lodash";

_.chain([1, 2, 3])
    .map(x => [x, x*2])
    .flatten()
    .sort()
    .value();

, которая может быть преобразована в следующую с помощью потока

import map from "lodash/fp/map";
import flatten from "lodash/fp/flatten";
import sortBy from "lodash/fp/sortBy";
import flow from "lodash/fp/flow";

flow(
    map(x => [x, x*2]),
    flatten,
    sortBy(x => x) 
)([1,2,3]);

Однако, когда я реализую это с помощью TypeScript,Я получаю следующую ошибку

Объект относится к типу unknown.ts (2571)

This error is highlighted on the x used in the map function.

Есть ли способ исправить это, чтобы TypeScript знал, с какими типами он имеет дело?

Ответы [ 3 ]

8 голосов
/ 21 июня 2019

Как интерпретируется JavaScript / TypeScript (примечание: код TypeScript переносится в JavaScript, который затем интерпретируется), когда вы используете цепочку, typScript знает о типе, с которым он имеет дело (то есть массив чисел), так как он стоит первым,Однако с потоком тип, над которым будут работать функции потока, указывается последним, поэтому он не знает, какие типы он будет использовать, поэтому необходимы универсальные средства или другой способ указания типов, которые будут использоваться.Кроме того, linter, генерирующий эту ошибку, интерпретирует код, поэтому он не знает, с какими типами обращаются, когда ввод вводится последним при использовании «потока».

Поскольку вы используете lodash с TypeScript, функции, которые вы используетеиспользуют вспомогательные обобщения для указания типов, с которыми они имеют дело.

Следовательно, вы можете указать, что вводится / выводится из функций lodash, следующим образом:

flow(
    map<number, [number, number]>(x => [x, x * 2]),
    flatten,
    sortBy(x => x)
)([1, 2, 3]);

или, как предлагает Дарека:

flow(
    map((x: number) => [x, x * 2]),
    flatten,
    sortBy(x => x)
)([1, 2, 3])

Но, опять же, это работает только потому, что мы указываем компилятору, какой тип будет использоваться.

Пример работы этих фрагментов кода можно найти здесь .

Обратите внимание, что входы / выходы функции были явно определены, например, «карта» указывает, что тип, который она будет перебирать, - это число, а результат операции - этокортеж.

5 голосов
/ 21 июня 2019

Метод _.flow() генерирует функцию pointfree .Это предотвращает вывод машинописным шрифтом типа ввода.

Чтобы решить эту проблему, назначьте функцию переменной и добавьте тип функции.Когда параметры функций и выходные данные объявлены, машинопись может вывести внутренние типы функций внутри потока.

После присвоения функции переменной вы можете вызвать ее ( sandobx ):

const fn: (numbers: number[]) => number[] = flow(
    map(x => [x, x*2]),
    flatten,
    sortBy(x => x) 
);

const result = fn([1,2,3]);

Или использовать утверждение типа, если хотите немедленно вызвать функцию ( песочница ):

type Fn = (numbers: number[]) => number[];

const result = (flow(
  map(x => [x, x * 2]),
  flatten,
  sortBy(x => x)
) as Fn)([1, 2, 3]);
5 голосов
/ 21 июня 2019

Мне нравится ответ Бена Смита, так как он был довольно познавательным для меня.Но я собирался предложить это

map((x: number) => [x, x*2])

или даже

map((x: any) => [x, x*2])

для более общих случаев.Кажется, это работает и получит как можно больше выводов, если вы не хотите быть слишком строгими.

...