Lodash Flow和TypeScript

时间:2019-06-21 08:43:47

标签: javascript typescript functional-programming lodash

我一直在关注有关Lodash的文章Why using _.chain is a mistake,该文章强调您可以使用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实现此操作时,出现以下错误

  

对象的类型为“未知”。ts(2571)

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

有什么办法可以解决这个问题,以便TypeScript知道它正在处理哪种类型?

4 个答案:

答案 0 :(得分:8)

当解释JavaScript / TypeScript时(注意:将TypeScript代码转换为JavaScript然后进行解释),当您使用链时,打字稿会首先知道其处理的类型(即数字数组)。 。但是,对于流,流函数要作用的类型是最后指定的,因此它不知道它将使用什么类型,因此需要泛型或另一种指示将要使用的类型的方法。另外,生成此错误的linter也在解释代码,因此当使用“ flow”输入最后一次时,它不知道要处理的类型。

在将lodash与TypeScript结合使用时,所使用的函数都支持泛型来指定它们要处理的类型。

因此,您可以如下说明lodash函数正在输入/输出的内容:

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

或dareka建议:

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

但这再次起作用,因为我们正在向编译器指示将要作用的类型。

可以找到这些代码段的工作示例here

请注意如何明确定义功能输入/输出,例如“ map”表示要迭代的类型是一个数字,操作的结果是一个元组。

答案 1 :(得分:5)

我喜欢本·史密斯的回答,因为这对我来说是很有教育意义的。但是我要建议这个

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

甚至

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

用于更一般的情况。如果您不想太严格,它似乎可以正常工作,并且会得到尽可能多的推断。

答案 2 :(得分:5)

_.flow()方法生成一个pointfree函数。这样可以防止打字稿推断输入的类型。

要解决此问题,请将函数分配给变量,然后添加函数的类型。声明函数参数和输出后,typescript可以推断流内部函数的内部类型。

将函数分配给变量后,可以调用它(sandobx):

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

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

或者如果您想立即调用函数(sandbox),请使用类型断言:

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

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

答案 3 :(得分:0)

我创建了一个帮助程序,可以让您将数组作为第一个参数传递,将运算符作为下一个参数传递,从而为您提供完整的输入方式:

import { orderBy, map, filter, flow } from 'lodash/fp'

export function chainFlow<T, R1, R2, R3, R4, R5>(
  values: T,
  f1: (t: T) => R1,
  f2: (t: R1) => R2,
  f3: (t: R2) => R3,
  f4: (t: R3) => R4,
  f5: (t: R4) => R5
): R5
export function chainFlow<T, R1, R2, R3, R4>(
  values: T,
  f1: (t: T) => R1,
  f2: (t: R1) => R2,
  f3: (t: R2) => R3,
  f4: (t: R3) => R4
): R4
export function chainFlow<T, R1, R2, R3>(
  values: T,
  f1: (t: T) => R1,
  f2: (t: R1) => R2,
  f3: (t: R2) => R3
): R3
export function chainFlow<T, R1, R2>(
  values: T,
  f1: (t: T) => R1,
  f2: (t: R1) => R2
): R2
export function chainFlow<T, R1>(values: T, f1: (t: T) => R1): R1
export function chainFlow<T>(
  values: T,
  ...funcs: ((...args: any[]) => any)[]
): any {
  return flow(funcs)(values)
}

// Example usage
const x = [1,2,3,4]

const y = chainFlow(x, filter(x => x > 3), map(x => x + "abc"))

完整的智能感知: enter image description here