-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Hi, thanks for your work on this library, it's been super helpful in making some of the more complex/deeply-nested forms I work with more type-safe.
I saw that there's a PR open for handling optional fields, which was one of the two pain points I've hit so far, so I'm excited for that to land. The other is for discriminated unions.
I've been using a pattern, like this (for example):
import * as z from 'zod';
const formSchema = z.object({
name: z.string(),
animal: z.discriminatedUnion('type', [
z.object({ type: z.literal('dog'), value: z.object({ canBark: z.boolean() }) }),
z.object({ type: z.literal('cat'), value: z.object({ canMeow: z.boolean() }) }),
]),
});
Effectively, the Animal value type is:
{ type: 'dog', value: { canBark: boolean } } | { type: 'cat', value: { canMeow: boolean } }
Many of the APIs I work with use a number of "oneOf" values, so I lean into these pretty heavily. Often, I will need to conditionally show different fields based on the selected type (in this example, animal.type
). I've put together a little CodeSandbox that shows the issues I'm running into: https://codesandbox.io/p/sandbox/hrymxc
I think there are two main issues with the approach I've taken here (maybe there's a better way?):
- I'm not able to focus the
type
path from a Lens that was focused toanimal
before without a TypeScript error:
This expression is not callable.
Each member of the union type '(<P extends "type" | "value" | "value.canBark">(path: P) => Lens<P extends `${infer K}.${infer R}` ? K extends requiredKeys<baseObjectOutputType<{ type: ZodLiteral<"dog">; value: ZodObject<{ canBark: ZodBoolean; }, "strip", ZodTypeAny, { ...; }, { ...; }>; }>> ? PathValueImpl<...> : K extends `${number}` ? never : n...' has signatures, but none of those signatures are compatible with each other.typescript(2349)
Interestingly, I noticed that I'm not getting the TS error if I lens.focus('animal.type')
or even lens.focus('animal.value.canBark')
from the root-level lens-- just the one that's already been focused to animal
.
- I'm trying to type narrow. I'm using
useWatch
to narrow based on the form value that the user selected (so I can show the appropriate inputs for their selection), but the lens, of course, isn't narrowed along with it.
Again, I really appreciate your work on this library, it's been a joy to work with so far! Thanks!