When using the valibot library with TypeScript, there’s a discrepancy in how optional fields are typed. Specifically, the optional validator is not retaining the undefined type for the password field. The expected type for the parsed result should be {email: string, password: string | undefined}, but the actual result is typed as {email: string, password: string}, suggesting that password is always present.
import * as v from 'valibot';
const Schema = v.object({
email: v.pipe(v.string(), v.email()),
password: v.optional(v.pipe(v.string(), v.minLength(8))),
});
const result = v.parse(Schema, {
email: 'jane@example.com',
// password: '12345678',
});
const test = {
email: result.email,
password: result.password
};
// expected type {email: string, password: string | undefined}
// current result: {email: string, password: string}
console.log(test);
Expected Behavior:
The parsed result should have a type of {email: string, password: string | undefined} to properly account for the absence of the password field in the input data.
Actual Behavior:
The result is typed as {email: string, password: string}, which implies that password is always defined, even if it is actually optional and can be absent.
Possible Cause:
This issue might be due to how valibot processes optional fields, or it could be a limitation in how TypeScript infers the types from the valibot schema. Even when password is omitted, it is still being treated as a string instead of string | undefined.
Problem Description:
When using the valibot library with TypeScript, there’s a discrepancy in how optional fields are typed. Specifically, the optional validator is not retaining the undefined type for the password field. The expected type for the parsed result should be
{email: string, password: string | undefined}
, but the actual result is typed as{email: string, password: string}
, suggesting that password is always present.Expected Behavior:
The parsed result should have a type of {email: string, password: string | undefined} to properly account for the absence of the password field in the input data.
Actual Behavior:
The result is typed as {email: string, password: string}, which implies that password is always defined, even if it is actually optional and can be absent.
Possible Cause:
This issue might be due to how valibot processes optional fields, or it could be a limitation in how TypeScript infers the types from the valibot schema. Even when password is omitted, it is still being treated as a string instead of string | undefined.
Examples:
In the playground correct behaviour: playground
With typescript v5.6.3:
and
My ts config: