-
-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RegExpExecArray does not match ArraySchema #946
Comments
This is because of the use of const GoodSchema = v.pipe(
v.union([v.number(), v.string()]),
// `number` (specific type) is assignable to `number` | `string` (base type)
v.number()
);
// The type checker won't accept this schema
const BadSchema = v.pipe(
v.union([v.number(), v.string()]),
// `null` is not assignable to `number` | `string`
v.null(),
); In the example associated with this issue, // The type checker generates a type error because this assignment is not safe
const test: RegExpExecArray | null = new Array<string>(); Based on how the pipeline is set up in the example associated with this issue, I recommend using this schema: const Schema = v.pipe(
v.string(),
// correct string - 2024.01.30
v.transform(value => /^(\d{4})\.\d{2}\.\d{2}$/.exec(value) ?? new Array<string>()),
v.length(2),
v.transform(value => Number(value[1])),
); |
Thanks, this helped. However, this doesn't seem very intuitive. Initially, I expected the schema check to always accept unknown as input, and then check the type and throw an error. This looks logical and quite convenient because my example looks clearer than yours. Is it possible to bring existing behavior to this? |
I think the current pipeline behavior is important because it helps avoid creating impossible schemas. Example: // Type error because: A value cannot be associated with a `string` and `number` type at the same time (impossible)
const Schema = v.pipe(v.string(), v.number()); But if you are sure you won't create a schema that always generates a runtime error (like in the example associated with this issue), you can return const Schema = v.pipe(
v.string(),
// This `transform` action returns `unknown` now
v.transform((value): unknown => /^(\d{4})\.\d{2}\.\d{2}$/.exec(value)),
v.array(v.string()),
v.length(2),
v.transform(value => Number(value[1])),
); Will this help? |
I like this solution better and will use it for now. What about the current behavior - is it really such a problem? After all, this also doesn't allow using completely valid schemes:
You can make this behavior configurable. Or check for such incompatibility in runtime and throw issue. |
I think there is always a way to create schemas with the current const Schema = v.object({test1: v.string(), test2: v.string()}); Making the behavior configurable is possible, but I am not sure if that would be ideal. @fabian-hiller Can you share your thoughts? Also, I think checking for incompatibility at runtime and throwing an issue will:
Fabian might be busy for a few days. So let's keep this issue open till we get a response. |
This is only necessary for the initial unknown input, but in your case the return type if I would rewrite your schema: import * as v from 'valibot';
const DATE_REGEX = /^\d{4}\.\d{2}\.\d{2}$/u;
const Schema = v.pipe(
v.string(),
v.regex(DATE_REGEX),
v.transform((input) => DATE_REGEX.exec(input)![1])
); |
What about an action that validates a a regex but also returns a regex or its captures? I have something alike by using rawTranform to avoid evaluating the regex twice. |
If you or anyone else has a good idea for naming and functionality, I am happy to consider such an action. Note that you can always write your own action. |
This is a very opinionated version because of the type of Regex we're using which is named captures, but something alike maybe:
|
I just want to parse a specific value from a string using RegExp. This works, but TS complains about types.
The text was updated successfully, but these errors were encountered: