見出し画像

null2undefined関数とundefined2null関数の紹介

こんにちわ。nap5です。


null2undefined関数とundefined2null関数の紹介をしたいと思います。


デモのドメインです。nullish(nullとundefinedを含む)でUnNeatな型になります。スキーマはzodライブラリで定義しています。

import { z } from "zod";

const BlogDataSchema = z.object({
  id: z.number().nullish(),
  title: z.string().nullish(),
  published: z.boolean().nullish(),
});

const AuthorDataSchema = z.object({
  id: z.number().nullish(),
  name: z.string().nullish(),
  age: z.number().nullish(),
  blogs: BlogDataSchema.array().nullish(),
});

type UnNeatData = z.infer<typeof AuthorDataSchema>;


デモデータです。

const data: UnNeatData = {
  id: null,
  name: "Jack Jackson",
  age: 38,
  blogs: [
    {
      id: null,
      title: "AAA",
      published: false,
    },
    {
      id: 2,
      title: null,
      published: false,
    },
    {
      id: null,
      title: null,
      published: true,
    },
  ],
};


DeepNonNullableはts-essentialsライブラリから使えますが、DeepNonUndefinedは以下の記事から流用してみました。




type PrimitiveOmitNull =
  | number
  | string
  | boolean
  | bigint
  | symbol
  | undefined;
type BuiltinOmitNull =
  | PrimitiveOmitNull
  | Function
  | Date
  | Error
  | RegExp;

// https://qiita.com/irico/items/ca02ba3ebf21fc96b062
// https://www.gaji.jp/blog/2022/09/02/10867/
type DeepNonUndefined<T> = T extends BuiltinOmitNull
  ? NonNullable<T>
  : { [key in keyof T]-?: DeepNonUndefined<T[key]> };


タイトルの関数になります。

const null2undefined = <T>(data: unknown): T => {
  const flatData: Record<string, unknown> = flatten(data);
  Object.keys(flatData).forEach((key) => {
    flatData[key] = flatData[key] === null ? undefined : flatData[key];
  });
  return unflatten(flatData);
};

const undefined2null = <T>(data: unknown): T => {
  const flatData: Record<string, unknown> = flatten(data);
  Object.keys(flatData).forEach((key) => {
    flatData[key] = flatData[key] === undefined ? null : flatData[key];
  });
  return unflatten(flatData);
};


最後に定義した関数を使ってみます。

type UnNeatInBoundData = DeepNonNullable<UnNeatData>;
type UnNeatOutBoundData = DeepNonUndefined<UnNeatData>;

console.log(data);
const result1 = null2undefined<UnNeatInBoundData>(data); // from db to web <<< InBound
console.log(result1);
const result2 = undefined2null<UnNeatOutBoundData>(result1); // from web to db >>> OutBound
console.log(result2);


実行結果です。

nullundefinedに置換されてインバウンド(from db to web)を達成でき、undefinednullに置換されてアウトバウンド(from web to db)を達成できているようです。

$ yarn do
{
  id: null,
  name: 'Jack Jackson',
  age: 38,
  blogs: [
    { id: null, title: 'AAA', published: false },
    { id: 2, title: null, published: false },
    { id: null, title: null, published: true }
  ]
}
{
  id: undefined,
  name: 'Jack Jackson',
  age: 38,
  blogs: [
    { id: undefined, title: 'AAA', published: false },
    { id: 2, title: undefined, published: false },
    { id: undefined, title: undefined, published: true }
  ]
}
{
  id: null,
  name: 'Jack Jackson',
  age: 38,
  blogs: [
    { id: null, title: 'AAA', published: false },
    { id: 2, title: null, published: false },
    { id: null, title: null, published: true }
  ]
}
Done in 0.95s.



デモコードです。



簡単ですが、以上です。

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