Ⓜ️

type-festのMergeDeep型を使ったマージ処理

2023/02/18に公開

type-festMergeDeep型を使ったマージ処理のデモを作ってみましたので、紹介です。

以下の部分の実装をしたデモになります。
https://github.com/sindresorhus/type-fest/blob/main/source/merge-deep.d.ts#L445-L456

デモコードです。

2つの型を用意します。

type Foo = {
  life: number;
  items: string[];
  users: { id: number; name: string }[];
  a: { b: string; c: boolean; d: number[] };
};

type Bar = {
  name: string;
  items: number[];
  users: { id: number; name: string }[];
  a: { b: number; d: boolean[] };
};

ramdaライブラリでポートされているmergeDeepWith関数を使って実装します。

const mergeDeep = <Source, Destination, Options extends MergeDeepOptions = {}>(
  source: Source,
  destination: Destination,
  options?: Options
): MergeDeep<Source, Destination, Options> => {
  // https://github.com/sindresorhus/type-fest/blob/main/source/merge-deep.d.ts#L416-L456
  // Make your implementation ...
  const mergedObj = mergeDeepWith<Source, Destination>(
    (x, y) => {
      // https://github.com/denoland/deno/blob/main/ext/node/polyfills/util.ts#L30-L32
      if (Array.isArray(x) && Array.isArray(y)) {
        return [...x, ...y];
      }
      if (x) return x;
      if (y) return y;
      return null;
    },
    source,
    destination
  );
  return mergedObj;
};

デモの2つの型にマッチするデータを用意します。

const a: Foo = {
  life: 1,
  items: ["a"],
  users: [
    {
      id: 1,
      name: "user1",
    },
    {
      id: 2,
      name: "user2",
    },
  ],
  a: {
    b: "@",
    c: false,
    d: [1, 2, 3],
  },
};

const b: Bar = {
  name: "bar",
  items: [4, 5, 6],
  users: [
    {
      id: 3,
      name: "user3",
    },
    {
      id: 4,
      name: "user4",
    },
  ],
  a: {
    b: 111,
    d: [true, false],
  },
};

実装した関数を実行すると結果が取得できます。

const result = mergeDeep<Foo, Bar>(a, b);

console.log(result);
// output
{
  life: 1,
  items: [ 'a', 4, 5, 6 ],
  users: [
    { id: 1, name: 'user1' },
    { id: 2, name: 'user2' },
    { id: 3, name: 'user3' },
    { id: 4, name: 'user4' }
  ],
  a: { b: '@', c: false, d: [ 1, 2, 3, true, false ] },
  name: 'bar'
}

簡単ですが、以上です。

Discussion