以下は、Zod を使って入れ子になったオブジェクトを定義した場合に、どのように中のオブジェクトの型や値を取り出すかの例です。
例1: 別々のスキーマとして定義する場合
まず、内側のオブジェクトのスキーマを別に定義し、それを親スキーマに組み込む例です。
import { z } from 'zod';
// 内側のオブジェクトのスキーマ
export const innerSchema = z.object({
firstName: z.string(),
lastName: z.string(),
});
// 親スキーマの定義
export const parentSchema = z.object({
user: innerSchema,
id: z.number(),
});
型の取り出し方
内側のオブジェクト型を取り出す
内側のスキーマから型を取り出すには、以下のようにします。
// innerSchema から型を取り出す場合
type UserType = z.infer<typeof innerSchema>;
// 結果: { firstName: string; lastName: string; }
親スキーマから内側のオブジェクト型を取り出す
親スキーマから内側のオブジェクトの型だけを取り出す場合、TypeScript のインデックスアクセス型を使います。
type ParentType = z.infer<typeof parentSchema>;
// 結果: { user: { firstName: string; lastName: string }; id: number; }
type UserFromParent = ParentType['user'];
// 結果は同じ: { firstName: string; lastName: string; }
値の取り出し方
たとえば、実際にデータをパースした後、内側のオブジェクトの値にアクセスするには次のようにします。
const data = {
user: {
firstName: "Taro",
lastName: "Yamada",
},
id: 123,
};
// parentSchema を使って検証・パース
const parsedData = parentSchema.parse(data);
// inner のオブジェクトは、parsedData.user として取り出せます
console.log(parsedData.user.firstName); // "Taro"
例2: インラインで入れ子に定義する場合
スキーマ定義内に直接入れ子のオブジェクトを定義した場合も同様です。
import { z } from 'zod';
const schema = z.object({
user: z.object({
firstName: z.string(),
lastName: z.string(),
}),
});
型の取り出し方
この場合、親スキーマから内側の型をインデックスアクセス型で取り出すことができます。
type SchemaType = z.infer<typeof schema>;
// 結果: { user: { firstName: string; lastName: string; } }
type UserType = SchemaType['user'];
// 結果: { firstName: string; lastName: string; }
値の取り出し方
パース後に値を取り出す方法は同じです。
const data = {
user: {
firstName: "Hanako",
lastName: "Suzuki",
},
};
const parsed = schema.parse(data);
console.log(parsed.user.lastName); // "Suzuki"
まとめ
型定義の抽出:
内側のスキーマから直接型を取り出す場合は z.infer
親スキーマから内側の型のみ取り出す場合は、z.infer['user'] のように記述します。
値の取り出し:
パース後のオブジェクトから、内側のオブジェクトは単にプロパティアクセス(例: parsedData.user)で取り出すことができます。
このように、Zod のスキーマで入れ子のオブジェクトを定義しても、型と値の両方を簡単に取り出すことが可能です。