Should we change the object
schema?
#1022
Replies: 7 comments 9 replies
-
Would it be possible to add a new method const Schema = v.object({
key1: v.string(), // key1: string
key2: v.optional(v.string()), // key2?: string | undefined
key3: v.nullish(v.string()), // key3?: string | null | undefined
key4: v.exactOptional(v.string()), // key4?: string
key5: v.nullable(v.string()), // key5: string | null
key6: v.undefinedable(v.string()) // key6: string | undefined
}); In backend scenarios, I frequently need to serialize objects and store them in Redis or a database. As you can see, I believe that there are only a few cases where it's necessary to distinguish between |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Since there are many cases where
// NOTE: All of the types mentioned are output types
// `optional` within `object`
const ObjectSchema = v.object({
// without default value
k1: v.optional(v.string()), // k1?: string
k2: v.optional(v.string(), "none"), // k2?: string
k3: v.optional(v.string(), "undefined"), // k3?: string | undefined
k4: v.optional(v.string(), "null"), // k4?: string | null
k5: v.optional(v.string(), "nullish"), // k5?: string | undefined | null
// with same default value
k6: v.optional(v.string(), "none", "default"), // k6: string
k7: v.optional(v.string(), "undefined", "default"), // k7: string
k8: v.optional(v.string(), "null", "default"), // k8: string
k9: v.optional(v.string(), "nullish", "default"), // k9: string
// with different default values (very rare but possible)
// for all the cases, the type of the key-value pair will be - key: string
k10: v.optional(
v.undefinedable(v.string(), "undefined_default"),
"optional_default"
),
k11: v.optional(
v.nullable(v.string(), "null_default"),
"optional_default"
),
k12: v.optional(
v.nullish(v.string(), "nullish_default"),
"optional_default"
)
});
// `optional` outside `object`
// `optional` in schemas 1, 2 and 3 acts like an identity function (won't change the output)
const Schema1 = v.optional(v.string()); // string
const Schema2 = v.optional(v.string(), "none"); // string
const Schema3 = v.optional(v.string(), "none", "default"); // string
const Schema4 = v.optional(v.string(), "undefined"); // string | undefined
const Schema5 = v.optional(v.string(), "undefined", "default"); // string
const Schema6 = v.optional(v.string(), "null"); // string | null
const Schema7 = v.optional(v.string(), "null", "default"); // string
const Schema8 = v.optional(v.string(), "nullish"); // string | undefined | null
const Schema9 = v.optional(v.string(), "nullish", "default"); // string
// using `optional` like shown below does not make sense as optional's default is not used at all
// so this and related cases are naturally avoided
const Schema10 = v.optional(
v.undefinedable(v.string(), "undefined_default"),
"optional_default"
); |
Beta Was this translation helpful? Give feedback.
-
Personally I think |
Beta Was this translation helpful? Give feedback.
-
Just wanted to say I really like the proposed solution and like correctness much more over |
Beta Was this translation helpful? Give feedback.
-
Hey everyone, thanks for your contributions! I followed @xcfox's idea in PR #1013. You can install it with the command below and report back if you like. A new official version on npm will follow soon.
|
Beta Was this translation helpful? Give feedback.
-
Valibot v1.0.0-beta.13 is available |
Beta Was this translation helpful? Give feedback.
-
Great news! Valibot v1 RC is just around the corner. There are only a few issues holding us back. One of them is issue #983, which may lead to a breaking change. That's why I want to discuss this with you before making a final decision. This post will explain the current situation and the reasons for the proposed changes.
The problem
Currently, Valibot does not distinguish between missing and undefined object entries. This leads to a mismatch between the input and output values of a schema and their types when TypeScript's
exactOptionalPropertyTypes
configuration is enabled.The solution
The solution to this mismatch is to finalize PR #1013 and change the implementation of
object
andoptional
to distinguish between missing and undefined object entries. To allow missing entries,optional
must be used as the outermost schema of an object entry. To explicitly allowundefined
as a value, another schema function calledundefinedable
must be used.The impact
As seen in the previous code example, defining an object entry that can be both missing and undefined gets a little verbose. This gets especially ugly if you define a default value for both cases.
To fix this, we could add a new function that covers both. The problem is that there is a third schema function called
nullable
that also allowsnull
values. So adding a new function to cover every possible combination ofoptional
,undefinedable
andnullable
would result in 7 functions in total. I doubt this will make the API any better.Let's discuss
What do you think? Should we distinguish between missing and undefined object entries and fully support TypeScript's
exactOptionalPropertyTypes
configuration? If so, should we removenullish
and only provide 3 strong primitives withoptional
,undefinedable
andnullable
? Or should we add 4 more functions to cover all possible combinations? If so, what names would you use?Your opinion matters to me. I encourage everyone to share their thoughts. Even quick feedback like "I like this ... and I don't like that ..." is welcome and will help to shape Valibot's future API design. Please discuss with us on here on GitHub and share your thoughts.
Beta Was this translation helpful? Give feedback.
All reactions