-
-
Notifications
You must be signed in to change notification settings - Fork 301
Open
Labels
Milestone
Description
Hello there, we found a bug in the discord channel in this schema :
import * as v from 'valibot';
const Schema = v.object({
data: v.pipe(
v.nullish(v.object({
videos: v.array(v.string()),
})),
v.transform(val => val?.videos ?? [])
),
})
type Foo = v.InferOutput<typeof Schema>;
// Foo['data'] should be only string[], not string[]|undefinedWhen we are using object with an array child AND if the object is using nullish | optional | exactOptional | nullable WITH a default value then InferOutput return the same type as InferInput instead of using the default value to evaluate output type.
So to have a better view about what's going on i tested it as well :
import * as v from 'valibot';
// This one does not work as expected
const nullish0 = v.nullish(v.object({ foo: v.array(v.string()) }), {
foo: [],
});
type nullishI0 = v.InferInput<typeof nullish0>;
type nullishO0 = v.InferOutput<typeof nullish0>;
// So we would have to do such tricks to make it works :
const nullish1 = v.pipe(
v.nullish(v.object({ foo: v.array(v.string()) })),
v.transform((input) => {
if (!input) {
return { foo: [] };
}
if (!input.foo) {
input.foo = [];
return input;
}
return input;
}),
);
type nullishI1 = v.InferInput<typeof nullish1>;
type nullishO1 = v.InferOutput<typeof nullish1>;
// However we do not have the same problem if `array` is not called inside an `object` call :
const nullish2 = v.nullish(v.object({ foo: v.string() }), {
foo: '',
});
type nullishI2 = v.InferInput<typeof nullish2>;
type nullishO2 = v.InferOutput<typeof nullish2>;
const nullish3 = v.nullish(v.array(v.string()), []);
type nullishI3 = v.InferInput<typeof nullish3>;
type nullishO3 = v.InferOutput<typeof nullish3>;
const nullish4 = v.nullish(v.array(v.object({ foo: v.string() })), []);
type nullishI4 = v.InferInput<typeof nullish4>;
type nullishO4 = v.InferOutput<typeof nullish4>;This schema can be easily edited to try with other actions with a CTRL + D edit and copy paste.
To see the problem with exactOptional we need a parent object :
import * as v from 'valibot';
const exactOptional0 = v.object({
data: v.exactOptional(v.object({ foo: v.array(v.string()) }), {
foo: [],
}),
});
type exactOptionalI0 = v.InferInput<typeof exactOptional0>;
type exactOptionalO0 = v.InferOutput<typeof exactOptional0>;