💎
z.inferを使いたくない
z.inferを使いたくない
- 型を制御できない
- zodが生成した型を使いたくない
- 自前の型でzodのスキーマを制御したい
z.inferを使う場合
import z from "zod";
const user = z.object({
id: z.string(),
email: z.string(),
name: z.string(),
age: z.number().optional(),
});
type User = z.infer<typeof user>;

z.inferを使わない場合
import z from "zod";
type User = {
id: string;
email: string;
name: string;
age?: number;
};
const user = z.object({
id: z.string(),
email: z.string(),
name: z.string(),
age: z.number(),
} satisfies { [K in keyof User]-?: z.ZodType<User[K]> });
再利用性を高めるために...
import z from "zod";
type User = {
id: string;
email: string;
name: string;
age?: number;
};
type SchemaFor<T> = { [K in keyof T]-?: z.ZodType<T[K]> };
const user = z.object({
id: z.string(),
email: z.string(),
name: z.string(),
age: z.number(),
} satisfies SchemaFor<User>);
SchemaForの役割
-
keyof TでTのキーを取得する -
[K in keyof T]でTのキーをループする -
-?でオプショナルを外す -
z.ZodType<T[K]>でzodの型に変換する -
{ [K in keyof T]-?: z.ZodType<T[K]> }でTのキーをzodの型に変換したオブジェクト型を作成する -
satisfiesで型チェックを行う
どう見える?
スキーマのプロパティが不足している時
コード
import z from "zod";
type User = {
id: string;
email: string;
name: string;
age?: number;
};
type SchemaFor<T> = { [K in keyof T]-?: z.ZodType<T[K]> };
const user = z.object({
id: z.string(),
email: z.string(),
name: z.string(),
// age: z.number().optional(),
} satisfies SchemaFor<User>);


User型にないプロパティがある時
コード
import z from "zod";
type User = {
id: string;
email: string;
name: string;
age?: number;
};
type SchemaFor<T> = { [K in keyof T]-?: z.ZodType<T[K]> };
const user = z.object({
id: z.string(),
email: z.string(),
name: z.string(),
age: z.number().optional(),
additional: z.any(),
} satisfies SchemaFor<User>);


スキーマの型が違う時
コード
import z from "zod";
type User = {
id: string;
email: string;
name: string;
age?: number;
};
type SchemaFor<T> = { [K in keyof T]-?: z.ZodType<T[K]> };
const user = z.object({
id: z.string(),
email: z.string(),
name: z.number(),
age: z.number().optional(),
} satisfies SchemaFor<User>);


最後に
挙動はSchemaForを調整すれば変えられるので用途に合わせて作ればいい。
Discussion