-
-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested variants #794
Comments
Thank you for reporting this issue. I think it is solvable, but I need more time to look into it. The main problem is that we currently ignore the discriminator for nested To fix this, we need some logic that recursively checks or filters the options of nested |
I will investigate whether it makes more sense to support multiple discriminators, or whether the outer |
The only advantage for multiple discriminators I see is that it makes the code a bit less messy. Depending on the situation it makes the schema less nested. |
I think I could solve the problem, but I need to prettify the code and write tests that cover every possible success and failure case. |
What default error message would you expect in this case? The problem is that both subdiscriminators are invalid, but if we were to return an issue for both, they would contradict each other and confuse the user. import * as v from 'valibot';
const Schema = v.variant('type', [
v.variant('subType1', [
v.object({
type: v.literal('A'),
subType1: v.literal('A'),
test1: v.string(),
}),
v.object({
type: v.literal('B'),
subType1: v.literal('B'),
test2: v.string(),
}),
]),
v.variant('subType2', [
v.object({
type: v.literal('A'),
subType2: v.literal('A'),
test3: v.string(),
}),
v.object({
type: v.literal('B'),
subType2: v.literal('B'),
test4: v.string(),
}),
]),
]);
const result = v.safeParse(Schema, {
type: 'A',
}); |
I think we basically have two options. We could return only the issue for the first subdiscriminator |
I'd say the second option would be the nicer one. |
The second option would mean that we return one general issue with two subissues, one for each missing/invalid discriminator. This is the same approach we currently use with The "problem" with this approach is that users usually do not write code to handle the subissues. Also, generating a useful general issue for two missing/invalid discriminators is complicated. For For now, I think we should just return one issue for the first missing/invalid discriminator. This is much easier to implement, probably more useful for the user, and it probably doesn't matter too much since the user should avoid such cases in the first place. For my provided schema, this would return the error message |
I think that seems reasonable for now just showing the first invalid discriminator. For my use case that would work out fine. |
I believe i bumped into a related issue, so noting here fwiw import * as v from 'valibot';
const LayoutConfig = v.variant('layout', [
v.object({ layout: v.literal('text-only') }),
v.object({
layout: v.picklist(['hero-image', 'side-image']),
image: v.pipe(v.string(), v.url()),
}),
v.object({
layout: v.literal('carousel'),
itemType: v.picklist(['deals']),
deals: v.pipe(
v.string(),
v.transform((deals) => deals.split(',')),
v.array(v.string()),
),
}),
]);
const SplashScreenConfig = v.object({
screen: v.literal('splashScreen'),
backgroundColor: v.optional(v.string()),
});
const FeedConfig = v.object({
screen: v.literal('feed'),
position: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
});
const DealsConfig = v.intersect([
v.object({
screen: v.literal('deals'),
position: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
}),
LayoutConfig,
]);
const CmsItem = v.intersect([
v.object({
id: v.string(),
title: v.string(),
url: v.optional(v.pipe(v.string(), v.url())),
cardDescription: v.string(),
}),
v.variant('screen', [SplashScreenConfig, FeedConfig, DealsConfig]),
]);
v.parse(CmsItem, {
id: '123',
title: 'Welcome',
screen: 'deals',
url: 'https://google.com',
cardDescription: 'Sample card description',
layout: 'carousel',
itemType: 'deals',
deals: 'abc,def,ghi',
}); and getting
|
No, your problem is not related to this issue. const CmsItem = v.intersect([
v.object({
id: v.string(),
title: v.string(),
url: v.optional(v.pipe(v.string(), v.url())),
cardDescription: v.string(),
}),
- v.variant('screen', [SplashScreenConfig, FeedConfig, DealsConfig]),
+ v.union([SplashScreenConfig, FeedConfig, DealsConfig]),
]); |
@ZerNico I am pretty close to the final implementation. I will explain you the new algorithm of |
v0.41.0 is available |
Hey @fabian-hiller,
i am currently trying to implement a relatively complex form using Valibot for validation.
Here is a simplified example of what I am trying to accomplish
This works fine if the data is valid but if it is not it always goes into the first subType variant and just shows the issues of that.
Using union also is not really an option because that would give me issues for all different paths but I only want the ones for the current selection.
Something like
would probably work but that seems relatively hard to implement.
Is there currently a way to accomplish something like this?
Thanks in advance! :)
The text was updated successfully, but these errors were encountered: