🐥
zod チートシート
はじめに
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
有益な記事ありがとうございます!!
嬉しいコメント誠にありがとうございます!共に良いハックライフを楽しみましょう!