我一直在关注有关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)
有什么办法可以解决这个问题,以便TypeScript知道它正在处理哪种类型?
答案 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"))