繁体   English   中英

将数组转换为 object 的正确 fp-ts 方法

[英]The proper fp-ts way to convert array into object

我是函数式编程的新手,但想学习最佳实践。

将数组转换为 object 的正确 fp-ts 方法是什么?

(items: Item[], keyGetter: (i: Item) => Key) => Record<Key, Item>

到目前为止,我使用自己的非 fp-ts 实现:

function isDefined<T>(value: T): value is Exclude<T, undefined> {
  return value !== undefined;
}

type TIdentifier = string | number;

export const arrayToRecord = <T1, T2 extends TIdentifier = string>(
  arr: T1[],
  getKeyName?: (item: T1) => T2
): Record<T2, T1> => {
  const hasKeyNameGetter = isDefined(getKeyName);
  return arr.reduce((acc, item) => {
    acc[
      hasKeyNameGetter ? (getKeyName as (item: T1) => T2)(item) : ((item as unknown) as T2)
    ] = item;
    return acc;
  }, {} as Record<T2, T1>);
};

这是实现您所要求的一种方法。

一些注意事项:

  • 由于字典是在运行时构建的并且对键没有保证,为了防止不安全的代码,返回类型是Record<string, A>
  • keyGetter不能是可选的,我们必须提供一种方法来想出 e 键
import * as A from 'fp-ts/ReadonlyArray'
import * as R from 'fp-ts/ReadonlyRecord'
import { pipe } from 'fp-ts/function'

const arrayToRecord = <A>(
  items: ReadonlyArray<A>,
  keyGetter: (i: A) => string,
): Readonly<Record<string, A>> =>
  pipe(
    items,
    A.reduce({}, (acc, item) => pipe(acc, R.upsertAt(keyGetter(item), item))),
  )

编辑

根据要求的示例:

const xs = [
  { id: 'abc', date: new Date() },
  { id: 'snt', date: new Date() },
]
const res = arrayToRecord(xs, (x) => x.id)

console.log(res)
// {
//   abc: { id: 'abc', date: 2021-04-06T13:09:25.732Z },
//   snt: { id: 'snt', date: 2021-04-06T13:09:25.732Z }
// }

编辑 2

pipe友好版:

declare const arrayToRecord: <A>(
  keyGetter: (i: A) => string,
) => (items: ReadonlyArray<A>) => Readonly<Record<string, A>>

interface X { id: string; date: Date }

declare const xs: ReadonlyArray<X>

pipe(
  xs,
  arrayToRecord((x) => x.id),
) // Readonly<Record<string, X>>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM