数组缩减和typescript中的可选值

时间:2018-04-25 20:58:15

标签: typescript

说我有以下可折叠界面:

export interface Foldable<F> {
  reduce: <A>(fn: (b: A, a: A) => A, initial: A, foldable: F) => A;
}

然后我想为数组实现它:

export const getArrayFold = <A>(): Foldable<Array<A>> => {
  return {
    reduce: (fn, initial, array) => {
      return array.reduce(fn, initial);
    }
  };
};

但编译器抱怨:

  

类型的参数'(b:A,a:A)=&gt; A'不能分配给参数   type'(previousValue:A,currentValue:A,currentIndex:number,array:   A [])=&gt;一个'。参数'a'和'currentValue'的类型是   不相容。       类型“A”不能分配给“A”类型。存在两种具有此名称的不同类型,但它们是不相关的。

我不明白这里有两种不同类型的A

2 个答案:

答案 0 :(得分:1)

如果更改泛型类型名称,则更容易看到正在发生的事情:

export const getArrayFold = <R>(): Foldable<Array<R>> => {

现在你将获得Type 'R' is not assignable to type 'A'array.reduce对当前值和上一个值使用不同的类型,因此您键入A(来自界面的泛型类型)并从R函数中键入getArrayFold。< / p>

您实际上没有将通用类型A传递给reduce,因此它认为它来自接口A,这实际上只是意味着它无法确定哪种类型应该是。

我发现这样做的一种方法是允许您的界面指定AF的类型:

export interface Foldable<F, A> {
  reduce: (fn: (b: A, a: A) => A, initial: A, foldable: F) => A;

现在您可以将数组函数编写为

getArrayFold = <R>(): Foldable<Array<R>, R>

当你打电话时,你可以做到

getArrayFold<string>().reduce((a, b) => a + b, '', ['hello', 'world']);

这会为您提供类型安全性,因此您无法在0 / .toFixed属性或类似内容上使用a作为值或b

答案 1 :(得分:1)

有两个错误:

  • 您需要提供哪种类型的数组。您无法从单个通用Array<T>获取它,您需要同时引入TArray<T>
  • reduce消耗的函数类型不足。纠正一个:(previousValue: A, currentValue: F) => A

说明:

如果您提供带有类型(例如string)的初始值来减少功能, previousValue 参数始终与 inital 相同

见官方TypeScript reduce declaration

interface Array<T> {
    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => U, initialValue: U): U;
}

完整代码(重构)

interface Foldable<F, T> {
    reduce: <A>(
        fn: (previousValue: A, currentValue: T) => A,
        initial: A,
        foldable: F
    ) => A;
}

const getArrayFold = <T>(): Foldable<T[], T> => ({
    reduce(fn, initial, array) {
        return array.reduce(fn, initial);
    }
});

// Real implementation usage
const array: number[] = [1, 2, 3]
const initial: string = "";
const fn: (previousValue: string, currentValue: number) => string = (a, b) => a + b;

const newValue: string = getArrayFold().reduce(fn, initial, array);

请参阅TypeScript playground

上的代码