Closed hanakannzashi closed 3 weeks ago
Can you provide a playground link? I am sure this is fixable. https://valibot.dev/playground/
Can you provide a playground link? I am sure this is fixable. https://valibot.dev/playground/
I guess issue is caused by wrong usage of never
in TDefault
, no type can extends never
except itself.
I would like to replace never
with undefined
, but the problem is that this does not work for our nullish
schema because there is a difference between providing undefined
as a default value and providing no default value. Providing undefined
as the default for nullish
would change every null
input to undefined
. That's why we can't specify .default
as undefined
, because that would lead to a bug with its output type. I know that never
is a hacky solution, but I don't know what else to do. Do you have any idea?
In the meantime you have two workarounds. You could add undefined
as a default value or you could ignore the TS error and cast the output type.
import * as v from 'valibot';
function mySchema<T extends v.GenericSchema>(schema: T) {
return v.pipe(v.optional(schema, undefined), v.check(() => true));
}
const schema = mySchema(v.number());
import * as v from 'valibot';
function mySchema<T extends v.GenericSchema>(schema: T) {
// @ts-expect-error
return v.pipe(
// @ts-expect-error
v.optional(schema),
v.check(() => true),
) as v.SchemaWithPipe<
[
v.OptionalSchema<T, never>,
v.CheckAction<v.InferOutput<T> | undefined, undefined>,
]
>;
}
const schema = mySchema(v.number());
I would like to replace
never
withundefined
, but the problem is that this does not work for ournullish
schema because there is a difference between providingundefined
as a default value and providing no default value. Providingundefined
as the default fornullish
would change everynull
input toundefined
. That's why we can't specify.default
asundefined
, because that would lead to a bug with its output type. I know thatnever
is a hacky solution, but I don't know what else to do. Do you have any idea?In the meantime you have two workarounds. You could add
undefined
as a default value or you could ignore the TS error and cast the output type.import * as v from 'valibot'; function mySchema<T extends v.GenericSchema>(schema: T) { return v.pipe(v.optional(schema, undefined), v.check(() => true)); } const schema = mySchema(v.number());
import * as v from 'valibot'; function mySchema<T extends v.GenericSchema>(schema: T) { // @ts-expect-error return v.pipe( // @ts-expect-error v.optional(schema), v.check(() => true), ) as v.SchemaWithPipe< [ v.OptionalSchema<T, never>, v.CheckAction<v.InferOutput<T> | undefined, undefined>, ] >; } const schema = mySchema(v.number());
I think this is because the definitions of null
and undefined
as a value or as a symbol of non-existence are unclear. I think null
should always be treated as a value and undefined
should be treated as a non-existence symbol (except within UndefinedSchema
). Thus, default
should ONLY work for undefined
, not for null
. Actually, Zod handles it this way as well.
const nullishSchema = z.number().nullish().default(1);
console.log(nullishSchema.parse(undefined)); // 1
console.log(nullishSchema.parse(null)); // null
const nullableSchema = z.number().nullable().default(1);
console.log(nullableSchema.parse(null)); // null
Both in nullish
and nullable
, default not work for null
, I think this is a expected behavior, not a issue.
Another example, many ORM like sequelize and TypeORM treat null
and undefined
separately, null
means this column is a null
value, undefined
means this column is not selected.
Requirement and solution:
z.number().nullish().default(0)
because valibot v.nullish(v.number(), 0)
will break this behavior.In summary (in valibot):
nullable
doesn't need default paramnullish
default should ONLY work for undefined
, not for null
If you still think a default value is necessary for null
, you should treat Default Value For Optional Value and Default Value For Nullable Value separately, seems tricky
Thank you for your recommendation! I like your idea and will think about it!
I am currently investigating your suggestion and think I will follow it.
v1.0.0-beta.3 is available
I don't understand why TypeScript tell me a error, I think this is a common use case