Typescript 和 Pluck 类型

标签 typescript functional-programming

我正在尝试实现 sumPluck 函数。它将允许调用者指定属于数组中对象的数字类型属性,然后将它们相加。

示例:

type A = { prop: number }

const arr: A[] = [{prop: 1}, {prop: 2}];

pluckSum("prop", arr); // 3

我知道如何输入 pluck,但我似乎无法让我的类型认识到它实际上只处理数字属性。这就是我所拥有的:

type PropertiesOfTypeNames<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
    type PropertiesOfType<T, U> = Pick<T, PropertiesOfTypeNames<T, U>>;

    type NumberProperties<T> = PropertiesOfType<T, number>;

    const pluckSum = <T, K extends keyof NumberProperties<T>>(arr: T[], k: K) =>
        pipe(
            arr,
            R.map(v => v[k]),
            R.sum
        );

我在 map 下收到一条错误消息:类型“T[string]”无法分配给类型“number”

因此,映射类型似乎并未表明 v[k] 是一个数字属性。我一定是做错了什么。

最佳答案

无论 Typescript 如何,我都想向您展示一种循环融合的替代方法,即消除冗余数组遍历。我使用 (b -> c) -> (a -> c -> d) -> a -> b -> d 类型的有点非正统的组合器获得循环融合(以 Hindley-Milner 表示法),我称之为 contramap2nd ,因为它与二元函数的第二个参数相反射(reflect)射。

长故事,短故事:

// (b -> c) -> (a -> c -> d) -> a -> b -> d
const contramap2nd = g => f => x => y =>
  f(x) (g(y));

const arrFold = f => init => xs =>
  xs.reduce((acc, x) => f(acc) (x), init);
  
const add = x => y => x + y;
const prop = k => o => o[k];

const pluckSum = k =>
  arrFold(
    contramap2nd(
      prop(k))
        (add)) (0);

console.log(
  pluckSum("foo") ([{foo: 1}, {foo: 2}, {foo: 3}]));

您可以对 add 的第二个参数进行反向映射当然,如果您不喜欢的话,可以手动contramap2nd .

请注意,您可以获得 map 的循环融合, contramap等人。

关于Typescript 和 Pluck 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57012247/

相关文章:

java - java8中累积对的函数式方法

javascript - 有人能解释一下这个解决方案是如何工作的吗

javascript - 将应用程序表达为 http.createServer 的参数

typescript - awesome-typescript-loader 仅加载/编译引用文件

angular - 指令 Angular 2 上的停止按钮单击事件

functional-programming - Tuple2 to Map转换的javaslang列表

angular - 如何检测ionic2中ion-searchbar的onfocus和blur事件?

typescript - Behavioursubject 不更新订阅者 onnext(value)

Java 8代码优化——删除if语句

functional-programming - 将节点插入树中 - Racket