見出し画像

zodライブラリを使ってプロパティの包含と除外の機能をもつuseCludeというフックを作ってみました

こんにちわ。nap5です。今回は小ネタです。

zodライブラリを使ってプロパティの包含と除外の機能をもつuseCludeというフックを作ってみました。


PrismaのDSLみたいに宣言的に抽出対象を指定したりできたら、便利だと思いチャレンジしてみました。もう少し仕上げる必要はあるかもしれませんが、このぐらいのほうがハンディかもです。


前回の記事と関連です。


データです。

[
  {
    "id": "p9z7aek9fi",
    "name": "Landon Glover",
    "age": 38,
    "blogs": []
  },
  {
    "id": "pga7t8prpl",
    "name": "Jack Jackson",
    "age": 38,
    "blogs": [
      {
        "id": "1",
        "title": "AAA"
      },
      {
        "id": "2",
        "title": "BBB"
      },
      {
        "id": "3",
        "title": "CCC"
      }
    ]
  },
  {
    "id": "tcz4kesu6p",
    "name": "Grace Dennis",
    "age": 44,
    "blogs": [
      {
        "id": "4",
        "title": "DDD"
      }
    ]
  }
]


useCludeフックです。

import { z } from "zod";

const useClude = (shape: z.ZodRawShape) => {
  const schema = z.object(shape);

  type Shape = z.infer<typeof schema>;

  type ShapeKeys = keyof Shape;

  const exclude = (...props: ShapeKeys[]) => {
    return schema.transform((res) => {
      const items = Object.keys(res) as ShapeKeys[];
      return items
        .filter((item) => {
          return !props.includes(item);
        })
        .reduce((acc, cur) => {
          return { ...acc, [cur]: res[cur] };
        }, {});
    });
  };

  const include = (...props: ShapeKeys[]) => {
    return schema.transform((res) => {
      const items = Object.keys(res) as ShapeKeys[];
      return items
        .filter((item) => {
          return props.includes(item);
        })
        .reduce((acc, cur) => {
          return { ...acc, [cur]: res[cur] };
        }, {});
    });
  };

  return {
    exclude,
    include,
  };
};


使い方です。

まずは指定したプロパティの包含です。

import data from "@/data/bebop.json";

const userShape: z.ZodRawShape = {
  id: z.string(),
  name: z.string(),
  age: z.number(),
  blogs: z
    .object({
      id: z.string(),
      title: z.string(),
    })
    .array(),
};
const { exclude, include } = useClude(userShape);
console.log(
  JSON.stringify(
    data.map((item) => include("blogs").parse(item)),
    null,
    2
  )
);

実行結果です。

[
  {
    "blogs": []
  },
  {
    "blogs": [
      {
        "id": "1",
        "title": "AAA"
      },
      {
        "id": "2",
        "title": "BBB"
      },
      {
        "id": "3",
        "title": "CCC"
      }
    ]
  },
  {
    "blogs": [
      {
        "id": "4",
        "title": "DDD"
      }
    ]
  }
]



次に指定したプロパティの除外です。


import data from "@/data/bebop.json";

const userShape: z.ZodRawShape = {
  id: z.string(),
  name: z.string(),
  age: z.number(),
  blogs: z
    .object({
      id: z.string(),
      title: z.string(),
    })
    .array(),
};
const { exclude, include } = useClude(userShape);
console.log(
  JSON.stringify(
    data.map((item) => exclude("name", "age").parse(item)),
    null,
    2
  )
);


実行結果です。


[
  {
    "id": "p9z7aek9fi",
    "blogs": []
  },
  {
    "id": "pga7t8prpl",
    "blogs": [
      {
        "id": "1",
        "title": "AAA"
      },
      {
        "id": "2",
        "title": "BBB"
      },
      {
        "id": "3",
        "title": "CCC"
      }
    ]
  },
  {
    "id": "tcz4kesu6p",
    "blogs": [
      {
        "id": "4",
        "title": "DDD"
      }
    ]
  }
]


簡単ですが、以上です。

この記事が気に入ったらサポートをしてみませんか?