fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖

Home Page:https://valibot.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot use `variant` together with `merge`

Karakatiza666 opened this issue · comments

I have a seemingly simple use-case where I'd like to do this:

export const authSchema = va.variant('security_protocol', [
  va.merge([
    va.object({
      security_protocol: va.literal('SASL_PLAINTEXT')
    }),
    saslPlaintextSchema // VariantSchema
  ]),
  va.merge([
    va.object({
      security_protocol: va.literal('SASL_SSL')
    }),
    sslSchema, // ObjectSchema
    saslPlaintextSchema // VariantSchema
  ])
])

But VariantSchema cannot be used inside merge(). The workaround would be to have sslSchema and saslPlaintextSchema be template functions that take a schema to merge with their internals inside their implementation, but in a case of >1 level of nesting this gets ugly quickly.

Sidenote: finally valibot has a discriminated union!

Yes, merge only supports object. It basically just spread its .entries into one object. This is not possible with variant.

import * as v from 'valibot';

const ObjectSchema1 = v.object({ key1: v.string() });

const ObjectSchema2 = v.object({ key2: v.number() });

// With merge
const MergedSchema1 = v.merge([ObjectSchema1, ObjectSchema2]);

// With spread
const MergedSchema2 = v.object({
  ...ObjectSchema1.entries,
  ...ObjectSchema2.entries,
});

There are many ways to construct such complex schemas. In some cases intersect may be a better option than merge. Read more here: https://valibot.dev/guides/intersections/