-
-
Notifications
You must be signed in to change notification settings - Fork 256
Open
Labels
enhancementNew feature or requestNew feature or requestworkaroundWorkaround fixes problemWorkaround fixes problem
Description
Hi,
How can I validate input based on the key name ?
If the key match /^foo(.+)$/ then it must be a string with maxLength 1
If the key match /^bar(.+)$/ then it must be a string with maxLength 10
otherwise no limitation
etc...
For example
{
"foo(x)": "a",
"bar(y)": "aaaaa",
"z": "xxxxxxxxxxxxxxxx"
}
is valid
but this one is not
{
"foo(x)": "aa"
}
because foo(x)
must have 1 char max
I tried:
const FooSchema = v.record(v.pipe(v.string(), v.regex(/^foo\(.+\)$/)), v.pipe(v.string(), v.maxLength(1)))
const BarSchema = v.record(v.pipe(v.string(), v.regex(/^bar\(.+\)$/)), v.pipe(v.string(), v.maxLength(10)))
const WildcardSchema = v.record(v.string(), v.number())
const Schema = v.union([
FooSchema,
BarSchema,
WildcardSchema,
])
const result = v.safeParse(Schema, {
'bar(a)': 'x',
'foo(b)': 'xxxxxx',
'z': 'xxxxxxxxxxxxxxxx'
});
It does not work it returns
Invalid format: Expected /^foo\(.+\)$/ but received "bar(a)"
and more
muningis
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestworkaroundWorkaround fixes problemWorkaround fixes problem
Projects
Milestone
Relationships
Development
Select code repository
Activity
muningis commentedon Apr 17, 2025
There's no first-class support for that, yet atleast. As it's needed for one of valibot codegen lib, it's likely it will come (but not guaranteed). However, there are some nuances with type-safety which makes it extra complicated.
As additional note,
v.union
is to validate against one of members, so it first tries to validate againstFooSchema
, then againstBarSchema
finally againstWildcardSchema
. Unfortunately, what works for merging multiple schemas (Merge Objects and Intersections) require use ofobject()
of which none works with record, as it's different checks. Merge requiresentries
property, whichrecord
does not have, and intersection validates against all schema -> so,bar(aa)
property will fail onFooSchema
Additionally, as mentioned this is bit complicated to define even with typescript, as you can not have wildcard properties when using pattern'ed keys
However, it works fine if there is no wildcard property. That type definition +
v.custom
makes it possible to implement that as per Playgroung example.You could add additional check for wildcard, but I'm not sure how to get that typed into that type.
fabian-hiller commentedon Apr 17, 2025
I think that I would validate it with custom logic with
check
in thepipe
of yourobject
orrecord
schema.muningis commentedon Apr 17, 2025
@fabian-hiller wdyt about adding first-class citizen schema for that? Only problem is inferring type literal, but I guess we could find inspiration in arktype :?
pgoerglerIaD commentedon Apr 17, 2025
@muningis thanks i will check if i find a way for the wildcard
@fabian-hiller it is possible to know the key name when using check() ?
fabian-hiller commentedon Apr 18, 2025
Here is one quick example. You can try it out in our playground.
I am open to discuss it, but it is important to me to think about a great API design first.
EskiMojo14 commentedon Apr 20, 2025
Maybe something like the below?
It then wouldn't be too hard to infer the right types for each pattern: Playground
As @muningis said though, I don't know if the wildcard is possible to accurately represent with Typescript.edit: after looking at what objectWithRest does (intersecting with another index signature), it does actually seem to work correctly:


For the keys you're essentially required to do the below every time:
It might be more convenient if there was an easier way of doing this, maybe:
In a similar vein, though much more complex, Zod v4 adds a template literal type builder (which constructs a regexp instance internally) such as below:
I suspect it would be a major job to add a similar API to Valibot though.