Closed4
[zod] discriminatedUnionとunionのふるまい
discriminatedUnion
について忘れそうなのでここに書いておく
zod: v3.23.8
を使用して検証した結果
得られる型
union
const schemaUnion = z.union([
z.object({
type: z.literal('WITH_FILE'),
file: z
.custom<File>()
.refine((file) => !(file instanceof File))
.refine((file) => ACCEPTED_FILE_TYPES.includes(file.type)),
}),
z.object({
type: z.literal('WITHOUT_FILE'),
}),
])
z.infer<typeof schemaUnion> // z.input, z.outoutも同様
// {
// type: "WITH_FILE";
// file: File;
// } | {
// type: "WITHOUT_FILE";
// }
discriminatedUnion
const schemaDiscriminatedUnion = z.discriminatedUnion('type', [
z.object({
type: z.literal('WITH_FILE'),
file: z
.custom<File>()
.refine((file) => !(file instanceof File))
.refine((file) => ACCEPTED_FILE_TYPES.includes(file.type)),
}),
z.object({
type: z.literal('WITHOUT_FILE'),
}),
])
z.infer<typeof schemaDiscriminatedUnion> // z.input, z.outoutも同様
// {
// type: "WITH_FILE";
// file: File;
// } | {
// type: "WITHOUT_FILE";
// }
一緒
バリデーション
union
schemaUnion.safeParse({ type: 'WITHOUT_FILE' }
// TypeError: Cannot read properties of undefined (reading 'type')
// .refine((file) => ACCEPTED_FILE_TYPES.includes(file.type)),
discriminatedUnion
schemaDiscriminatedUnion.safeParse({ type: 'WITHOUT_FILE' })
// {
// "success": true,
// "data": {
// "type": "WITHOUT_FILE"
// }
// }
unionの場合、type: "WITH_FILE:
のrefineの処理まで行っている
discriminatedUnionはそうではない
シンプルなスキーマだとunionでもdiscriminatedUnionと同じ用なふるまいをする
なぜ?
const schemaUnion = z.union([
z.object({
type: z.literal('WITH_FILE'),
stringField: z.string().refine((v) => v.length > 0),
}),
z.object({
type: z.literal('WITHOUT_FILE'),
}),
])
schemaUnion.safeParse({ type: 'WITHOUT_FILE' }
// {
// "success": true,
// "data": {
// "type": "WITHOUT_FILE"
// }
// }
refineの処理も通っていないようだ
このスクラップは1ヶ月前にクローズされました