-
Notifications
You must be signed in to change notification settings - Fork 934
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
Fix ObjectSchemaOf type definition #1170
Conversation
I actually don't think you want to add the Lazy here. What is the use case? |
Something like this, where the snippet below is used for a field in a Yup.array(
Yup.lazy<YupSchema<ModuleData>>(element => {
// ... dynamic logic here
})
); |
BTW, #1169 already added Lazy to the ArraySchema generic within |
yeah i see. hmm I am a bit concerned that this will break other common cases like #1155 It probably makes sense to have a common interface shared between lazy and schema (there is already one simple one) but unsure if that would break other stuff... |
I don't think it breaks that use case, does it? Changing the type definition to add |
yeah that's true for this specific change, but technically it's an incomplete change, since object properties also accept Lazy so you fix your example above but this still doesn't work i think?
|
Okay, I just committed the |
src/index.ts
Outdated
? // we can't use ObjectSchema<{ []: SchemaOf<T[k]> }> b/c TS produces a union of two schema | ||
ObjectSchemaOf<T[k]> | ||
: BaseSchema<Maybe<T[k]>, AnyObject, T[k]>; | ||
[k in keyof T]-?: SchemaOf<T[k]> | Lazy<SchemaOf<T[k]>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see the old comment here. We can't use SchemaOf<T[k]>
because of how TS applies the types over the conditional in SchemaOf. Basically if the input type is something like string | undefined
, you get SchemaOf<string> | SchemaOf<undefined>
, not SchemaOf<string | undefined>
, The behavior is different for passing the generic to a concrete type like BaseSchema
. Just means some duplication
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay... I'm really confused about what's going on here (and I've been playing with it for two hours now). Either I'm doing something wrong, or it seems like that comment is backwards. Can you look at the minimal example I made in this commit? 8bf7689
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I somewhat suspect the issue is with my example code (FormData
/buildNestedValidator
), not the Yup type definitions... but I can't figure out the right way, either. I'm not sure how to translate my recursive FormData
to a corresponding SchemaOf
type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ha, I think I figured out what's going on. I'll get back to you soon with this sorted out. Recursive types are... fun.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I added a commit that adds lazy to field values for object schemas.
And in case you wanted an explanation on how I got so confused:
interface FormData {
[K: string]: string | FormData;
}
type FormDataSchema = ObjectSchema<{
[K: string]: SchemaOf<string> | FormDataSchema;
}>;
export const buildNestedValidator = (
path: string[],
validator: SchemaOf<string> | FormDataSchema,
): FormDataSchema => {
const [head, ...rest] = path;
const result: SchemaOf<string> | FormDataSchema =
rest.length === 0 ? validator : buildNestedValidator(rest, validator);
return objectCreate({ [head]: result });
};
const foo: FormData = { foo: '', bar: { baz: '' } };
const val = buildNestedValidator(['bar', 'baz'], stringCreate().required());
val.validate(foo);
I was trying to use SchemaOf<FormData>
originally, but that wasn't working. The solution was to create the FormDataSchema
type and use it instead. I think that's because of how the union gets distributed - e.g. SchemaOf<string | string[]>
vs SchemaOf<string> | SchemaOf<string[]
. Something along those lines - my brain hurts at the moment.
Anyways, that's all irrelevant to the actual change in this PR and is just context on how I got so tripped up testing against my own code base. I went ahead and rebased to squash my mess - this is ready for you to review and potentially merge now.
781c50a
to
4e3e48f
Compare
Hi, any thoughts on the current state of this MR? |
will get back to you next week, on vacation! |
@jquense quick reminder about this PR. Hope you had a good vacation, too! |
Thanks for working with me on this PR and merging it! Do you have plans to make a new release with this change? It would help me out when you get a chance so that I can get rid of some temporary workaround code, but it isn't urgent. |
Follow up to #1169, because in my haste to rebase I overlooked adding
Lazy
to theArraySchema
generic inObjectSchemaOf
. I also simplified theObjectSchemaOf
definition since it doesn't need to repeat theSchemaOf
definition. I also fixed my incorrect formatting from #1169.I've tested this against my own project via
yarn link
so I know it at least works for my use cases.