4

I have an object with a numeric property. I'd like to make sure that the number has only up to 2 decimal digit.

e.g: 1 // good 1.1 // good 1.11 // good 1.111 //bad

Is there way to do that?

Looked at Zod's documentation and searched the web. Found that i could have done it easily if my property was a string. Not sure about number.

Uri
  • 43
  • 1
  • 4

1 Answers1

4
z.number().multipleOf(0.01)

will do the hack(yes, it can work with non-integer too!).

However, I worry about IEEE 754 representation issue(it even has its own name - but I forgot - and is not specific to JS), when

z.number().multipleOf(0.01).parse(0.1 + 0.1 + 0.1)

will throw, since 0.1 + 0.1 + 0.1 under the hood becomes 0.300000000004

Maybe refine() will be more reliable with checking against Number.EPSILON:

z.number()
  .refine(x => x * 100 - Math.trunc(x * 100)< Number.EPSILON)
  .parse(0.1 + 0.1  + 0.1) // ok

[upd] as @captain-yossarianfromUkraine noticed, Number.EPSILON should help with float-number thing

PS cannot evaluate this approach against z.custom() proposed by @vera

skyboyer
  • 22,209
  • 7
  • 57
  • 64
  • 1
    Try to use `Number.EPSILON` to handle `0.1+0.2` issue. See [example](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON) which is taken from docs – captain-yossarian from Ukraine Jan 31 '23 at 07:24
  • 1
    @captain-yossarianfromUkraine you're right. I tried yesterday with EPSILON and comparison did return `false` to me. But today it's `true` ¯\\_(ツ)_/¯ – skyboyer Jan 31 '23 at 11:21
  • Tnx for this answer! Great! I'm actually fine with '0.1 + 0.1 + 0.1' to fail, i'm getting an object with a number property. This number has to be with only up to two decimal digits, I don't care how it was created, if my api's user got `0.300000000004` because he/she added '0.1 + 0.1 + 0.1' and did not validate at his side that there are more decimal digits its his own problem. tnx again! – Uri Feb 01 '23 at 05:04