-
-
Notifications
You must be signed in to change notification settings - Fork 246
Variant / Discriminated union based on a subkey #1108
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
Comments
This has been brought up in Zod as well: colinhacks/zod#1868 |
I will consider supporting an API like this in the long run: const FieldSchema = v.variant(['fieldConfig', 'type'], [
AddressFieldSchema,
...
]) Would you be interested in investigating the implementation? The hard part will be getting the types right and implementing the validation without adding a lot of code to the bundle size. |
In the meantime you can just write: const FieldSchema = v.variant('fieldConfig', [
AddressFieldSchema,
...
]) |
With this workaround, the types aren’t narrowed properly though |
If this is the case, it is a limitation of TypeScript and not Valibot. Can you try defining such a type with pure TypeScript types? |
Surely possible with typescript by using template literal types and accessing object deeply. react-hook-form has something similar. However types performance is absolute tragedy with such usage. |
@fabian-hiller just tried it and indeed it’s a TS limitation... Here is a reproduction |
I suppose there’s no difference between The best thing to do here is just use type guards, I think |
Managed to define such type with Typescript: It's possible to deep-check value with path and expected value, and get required value. But I can't get function to do it's job
this one doesn't narrow down |
I've "semi" working (partial replication of However, to even use that discriminated union, it would probably require helper function - but in best case scenario it would be a matcher function (like a switch) |
|
I would probably still use |
@muningis I am very sorry for being so slow to respond. I have almost no time at the moment. I will try to catch up in the next few days. |
No worries. It's just experimental POC PR just to even get idea if it's possible. |
I’ve been thinking about it more lately, and I think implementing something like distributed union with a nested discriminant would be swimming against the tide. It doesn’t work in TypeScript yet, and there’s an open issue for it as well. I’d say it would be wisest to wait until TypeScript expands the narrowing rules. The feature itself — in my case — would just be making up for a bad API design, and creating type guards manually is still a great option. @fabian-hiller feel free to close this issue. |
I'd also love to have something for this. Currently using pattern: const propertiesSchema = variant('name', [
looseObject({
name: literal('body_type'),
value: picklist([
// ...
])
}),
looseObject({
name: literal('brand'),
value: string()
}),
looseObject({
name: literal('condition'),
value: picklist([
// ...
])
})
]) exporting separate types: export type BodyType = Extract<InferOutput<typeof propertiesSchema>, { name: 'body_type' }>
export type Brand = Extract<InferOutput<typeof propertiesSchema>, { name: 'brand' }> using: const bodyType = (car.properties.find(({ name }) => name === 'body_type') as BodyType).value which feels so dirty 😭 |
@vladshcherbin I think your code is not related to this issue or am I wrong? This seems more like a TS inference limitation when using |
@vladshcherbin It's working without deconstruction. Tested on Not working 🚫: const bodyType = car.properties.find(({ name }) => name === 'body_type')?.value
// string | undefined Working ✅: const bodyType = car.properties.find((property) => property.name === 'body_type')?.value
// "picklist_1" | "picklist_2" | undefined |
@vladshcherbin - that would require full code shown. However |
Let’s say I’m validating data of this shape:
The
value
shape is dependent on the field type.Is there an ergonomic way to validate such shape?
Something like this (not working, just to give an idea):
I don’t insist on a dot notation API, if there’s an ergonomic way to do it already, please do tell.
The text was updated successfully, but these errors were encountered: