Skip to content

fix: type each temporal format to admit what its regex accepts - #36

Open
maxholman[bot] wants to merge 4 commits into
masterfrom
fix/date-time-literal-type
Open

maxholman[bot] wants to merge 4 commits into
masterfrom
fix/date-time-literal-type

Conversation

@maxholman

@maxholman maxholman Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Every temporal format's generated type admits each value its regex accepts, so a date-time such as 2024-01-01t00:00:00Z or 2024-01-01 00:00:00Z, which RFC 3339 allows, assigns to the type the schema outputs. Each format's regex and type sit in one table, and valibot.ts imports the alias from types.ts and runs the regex in the same v.custom that types the output, so the literal is written out once and the typing step checks the value.

An x-typescript-hint that names a generated type, such as EmbedUrl, compiles in valibot.ts, which imports each type it references that types.ts exports.

A consumer that inspects issue types sees custom where a failed temporal check reported regex; the message is still the format name.

This conflicts with the open fix/ts-import-specifiers work near the importLazyTypes call in lib/process-document.ts, renamed here to importNamedTypes. Whichever lands second rebases.

maxholman and others added 4 commits November 7, 2026 19:29
A hint that names a generated type, such as `EmbedUrl`, reached valibot.ts
as `v.custom<EmbedUrl>` with no import, so the module did not compile. The
validators module now imports every type it references that the types
module exports, which also covers the annotations on lazy refs.

Co-Authored-By: LLM <noreply@block65.dev>
The regex that checks a format and the template-literal type it produces
were written out in both generators, so a change to one could miss the
other.

Co-Authored-By: LLM <noreply@block65.dev>
The date-time regex accepts `T`, `t` or a space between the date and the
time, as RFC 3339 allows, but the generated type admitted only `T`. A value
such as `2024-01-01t00:00:00Z` passed validation and still did not assign
to the type.

Co-Authored-By: LLM <noreply@block65.dev>
The generated validator ran the format's regex in `v.regex` and then
narrowed the output with `v.custom<…>(() => true)`, a step that accepts
anything. One `v.custom` now runs the regex and types the output, and a
component schema names its alias from the types module, so the template
literal is written out once. A failed check reports a `custom` issue where
it reported `regex`.

Co-Authored-By: LLM <noreply@block65.dev>
Comment thread lib/valibot.ts
function temporalHintSchema(format: string | undefined) {
const type = temporalTypeHint(format);
return type ? `v.custom<${type}>(() => true)` : undefined;
return `v.custom<${typeName ?? temporal.type}>((input) => typeof input === "string" && ${temporal.regex}.test(input), ${message})`;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants