-
-
Notifications
You must be signed in to change notification settings - Fork 269
Closed
Labels
fixA smaller enhancement or bug fixA smaller enhancement or bug fixintendedThe behavior is expectedThe behavior is expectedpriorityThis has priorityThis has priority
Description
#385 was resolved by adding v.undefinedable
with different typing from v.optional
:
import * as v from "valibot";
const optional_schema = v.object({ field: v.optional(v.number()) });
type OptionalOutput = v.InferOutput<typeof optional_schema>;
// { field?: number }
const undefinedable_schema = v.object({ field: v.undefinedable(v.number()) });
type UndefinedableOutput = v.InferOutput<typeof undefinedable_schema>;
// { field: number | undefined }
However, this typing is inconsistent with the runtime behavior: at runtime, both schemas accept and return both of {}
and { field: undefined }
. This means that both schemas break type safety with tsc --strict --exactOptionalPropertyTypes
.
const a = v.parse(optional_schema, { field: undefined });
if ("field" in a) { // narrows a.field to string
const n: number = a.field; // oops, this is undefined
}
const b = v.parse(
v.union([undefinedable_schema, v.object({ bogus: v.string() })]),
{}
);
if (!("field" in b)) { // narrows b to { bogus: string }
const s: string = b.bogus; // oops, this is undefined
}
Either the types should be adjusted to match the runtime behavior, or the runtime behavior should be adjusted to match the types.
Zod does the former:
import { z } from "zod";
const optional_schema = z.object({ field: z.optional(z.number()) });
type OptionalOutput = z.output<typeof optional_schema>;
// { field?: number | undefined }
Metadata
Metadata
Assignees
Labels
fixA smaller enhancement or bug fixA smaller enhancement or bug fixintendedThe behavior is expectedThe behavior is expectedpriorityThis has priorityThis has priority