🐥

zod チートシート

2023/10/24に公開2

はじめに

API 通信、フォームバリデーション、データ処理などでよく使う Zod。公式ドキュメントをにらめっこしながら書いているんですが、サクッとみれるチートシートのようなものが欲しくなり、作成してみました。
サクッと見れるようにしたかったので、よく使うものをベースにしていて、使い方のコードはトグルで表示する形式にしています。

Zod とは

Zod は、TypeScript 向けの強力なスキーマバリデーションおよびデータバリデーションライブラリです。Zod を使用すると、オブジェクトやデータの検証、バリデーション、変換を行う際に型安全性を保ちながら、簡潔でわかりやすいコードを記述できます。

検証

schema.parse(value) => value | throw ZodError

z.string().parse("tuna"); // => "tuna"
z.string().parse(12); // => throw ZodError

ZodErrorはこんな感じです。

ZodError: [
  {
    code: "invalid_type",
    expected: "string",
    received: "number",
    path: [],
    message: "Expected string, received number",
  },
];

強制的に型を当てはめたい場合は、coerceを使います。

z.coerce.string().parse("tuna"); // => "tuna"
z.coerce.string().parse(12); // => "12"
z.coerce.string().parse(true); // => "true"

以後の検証で使う関数はこちらになります。

コードを表示する
const check = (valid) => {
  try {
    console.log(valid);
  } catch (error) {
    console.log(error);
  }
};

primitive,array,enum,object について

1. primitive

function 説明
z.string() "tuna" 文字列を表す型
z.number() 12 数値を表す型
z.boolean() true 真偽値を表す型
z.date() new Date("2023-10-11") 日付を表す型
z.undefined() undefined
z.null() null
z.void() void (() => {})
z.nan() NaN

string

function 説明
z.string().max(5) 最大 5 文字の文字列
z.string().min(5) 最小 5 文字の文字列
z.string().length(5) ちょうど 5 文字の文字列
z.string().email() Email アドレスのバリデーション
z.string().url() URL のバリデーション
z.string().regex(/^[A-Z]\d{3}$/) 正規表現を使用したバリデーション
z.string().includes("apple") "apple"を含むかのバリデーション
z.string().startsWith("http://") "http://"で始まるかのバリデーション
z.string().endsWith(".com") ".com"で終わるかのバリデーション
z.string().datetime() ISO 8601 形式の日時

string(translate)

function 説明
z.string().trim() 文字列の前後の余分な空白文字(空白、タブ、改行など)を削除
z.string().toLowerCase() 文字列内の全ての文字を小文字に変換
z.string().toUpperCase() 文字列内の全ての文字を大文字に変換

number

function 説明
z.number().gt(5) <
z.number().gte(5) <=
z.number().lt(5) >
z.number().lte(5) >=
z.number().int() 整数かどうか
z.number().positive() > 0
z.number().nonnegative() >= 0
z.number().negative() < 0
z.number().nonpositive() <= 0
z.number().multipleOf(5) 割り切れるかどうか

primitive option

function 説明
.optional() undefined を付与
.nullable() null を付与
.nullish() undefined と null を付与
コードを表示する
check(z.string().parse("example"));

// optional()
check(z.string().optional().parse(undefined));

// nullable()
check(z.string().nullable().parse(null));

// nullish()
check(z.string().nullish().parse(null));
check(z.string().nullish().parse(undefined));

2. array

check(z.string().array().parse(["taro", "jiro"]));

3. enum

const FishEnumSchema = z.enum(["Salmon", "Tuna", "Trout"]);
type FishEnum = z.infer<typeof FishEnumSchema>;
// 'Salmon' | 'Tuna' | 'Trout'

const VALUES = ["Salmon", "Tuna", "Trout"] as const;
const FishEnumSchema = z.enum(VALUES);

FishEnumSchema.enum; // => { Salmon: "Salmon", Tuna: "Tuna", Trout: "Trout" }
FishEnumSchema.options; // ["Salmon", "Tuna", "Trout"];

4. object

// all properties are required by default
const Dog = z.object({
  name: z.string(),
  age: z.number(),
});

// extract the inferred type like this
type Dog = z.infer<typeof Dog>;

// equivalent to:
type Dog = {
  name: string;
  age: number;
};

object function

function 説明
.shape.key key schema を取り出す
.keyof() key の列挙型
.extend() Object の拡張
.merge() Object の合体
.pick({key:true}) 特定のキーのみ保持
.omit({key:true}) 特定のキーを削除
.partial() undefined を付与
.partial({key:true}) 特定のキーに undefined を付与
.required() 必須にする
コードを表示する
const ObjectSchema = z.object({
  id: z.number(),
  name: z.string(),
  username: z.string(),
});

// .shape.arg
check(ObjectSchema.shape.name.parse("taro"));

// .keyof()
check(ObjectSchema.keyof().parse("username"));

// .extend()
check(
  ObjectSchema.extend({ email: z.string() }).parse({
    id: 1,
    name: "taro",
    username: "tanaka taro",
    email: "taro@gamil.com",
  })
);

// .merge()
const MergeSchema = z.object({
  email: z.string(),
  address: z.string(),
});
check(
  ObjectSchema.merge(MergeSchema).parse({
    id: 1,
    name: "taro",
    username: "tanaka taro",
    email: "taro@gamil.com",
    address: "tokyo",
  })
);

// .pick({key:true})
check(ObjectSchema.pick({ name: true }).parse({ name: "taro" }));

// .omit({key:true})
check(
  ObjectSchema.omit({ name: true }).parse({
    id: 1,
    username: "tanaka taro",
  })
);

// .partial()
check(ObjectSchema.partial().parse({}));

// .partial({key:true})
check(
  ObjectSchema.partial({ name: true }).parse({
    id: 1,
    username: "tanaka taro",
  })
);

// .required()
check(
  ObjectSchema.partial().required().parse({
    id: 1,
    name: "taro",
    username: "tanaka taro",
  })
);

// .required({key:true})
check(ObjectSchema.partial().required({ id: true }).parse({ id: 1 }));

その他の機能

function 説明
.refine(valid,error) valid で検証(OK => value, NG => error)
.transform() 変化される
.default(value) デフォルトの値を設定する
.catch(value) バリデーションエラーの時の値を設定する
コードを表示する
// refine():OK
check(
  z
    .string()
    .refine(
      (val) => val.length > 3,
      (val) => ({ message: `${val} is not more than 10 characters` })
    )
    .parse("example")
); // => example

// refine():NG
check(
  z
    .string()
    .refine(
      (val) => val.length > 10,
      (val) => ({ message: `${val} is not more than 10 characters` })
    )
    .parse("example")
); // => error(message: 'example is not more than 10 characters')

// transform()
check(
  z
    .string()
    .transform((val) => val.length)
    .parse("example")
); // => 7

// 組合せ
check(
  z
    .string()
    .transform((val) => val.toUpperCase())
    .refine((val) => val.length > 3)
    .parse("example")
); // => EXAMPLE

// default()
check(z.string().default("example").parse(undefined)); // => example

// catch("example")
check(z.string().catch("example").parse(4)); // => example

// object & catch()
const ObjectSchema = z.object({
  id: z.number(),
  name: z.string(),
  username: z.string(),
});

check(
  ObjectSchema.extend({ email: z.string() })
    .catch({
      id: 2,
      name: "jiro",
      username: "suzuki jiro",
      email: "jiro@gamil.com",
    })
    .parse({
      id: 1,
      name: "taro",
      username: "tanaka taro",
    })
); // => { id: 2, name: 'jiro', username: 'suzuki jiro', email: 'jiro@gamil.com' }

エラーメッセージ

check(z.string().min(1, { message: "入力してください" }).parse(""));

いかがだったでしょうか?

もし記事があなたのお役に立ったなら、ぜひ「いいね!」ボタンをクリックしてくださいね。

Discussion

KenshiroKenshiro

有益な記事ありがとうございます!!

まさでぶまさでぶ

嬉しいコメント誠にありがとうございます!共に良いハックライフを楽しみましょう!