fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖
https://valibot.dev
MIT License
6.32k stars 204 forks source link

Need help using number schema with string values #881

Closed stackoverfloweth closed 4 weeks ago

stackoverfloweth commented 1 month ago

There are several reasons why an input that expects a number would use type="text". Fundamentally that means my model is going to have a string but I want to use v.number() with all the min/max/etc actions.

I also hoped that I could use v.parse to ensure that if the string value passes validation, valibot can also be responsible for parsing the string to number before doing anything with the data.

When I try to pass a string value into schema v.number() I get

Invalid type: Expected number but received "123"

fabian-hiller commented 1 month ago

Hey 👋 here is a fix. Let me know if that works for you. string validates the datatype of the input, decimal makes sure it is a number wrapped in a string, transform converts it to a number and the rest is probably clear to you.

import * as v from 'valibot';

const Schema = v.pipe(
  v.string(),
  v.decimal(),
  v.transform(Number),
  v.minValue(10),
  v.maxValue(20)
);
stackoverfloweth commented 1 month ago

@fabian-hiller thank you for this! I think I understand what's happening, though I'm a bit confused why v.decimal() is special? I expected to be able to also just v.integer() but that's not true. Furthermore, I though okay that's fine that v.decimal() is special, I can always narrow it to being an integer with an additional action like

v.pipe(
  v.string(),
  v.decimal(),
  v.transform(Number),
  v.integer(),
  v.minValue(10),
  v.maxValue(20)
);

However, this seems to fail

ValiError: Invalid decimal: Received "13.23"

I tried changing v.transform(Number) to v-transform(parseFloat) but that didn't change the error

fabian-hiller commented 1 month ago

What version of Valibot are you using? We changed/fixed decimal a few weeks ago. Feel free to share a playground link: https://valibot.dev/playground/

stackoverfloweth commented 1 month ago

thanks @fabian-hiller, I'll update to latest and see if that helps. I noticed a similar deal with dates, do you have a suggestion for values stored as string but expected to output to Date. For example when you're using <input type="date">.

fabian-hiller commented 4 weeks ago

Yes, you could expect a string, check its formatting and transform it to a date. Here is an example. Check it out in this playground.

import * as v from 'valibot';

const Schema = v.pipe(
  v.string(),
  v.isoDate(),
  v.transform((input) => new Date(input)),
);