suretype icon indicating copy to clipboard operation
suretype copied to clipboard

bug: defaults are not working correctly

Open moltar opened this issue 3 years ago • 2 comments

The defaults option is not working correctly.

In the following example, I have two approaches, both of which are faulty.

should fill in defaults with require

In this case, I am expecting the default to be set to 0, and then mark it as required, thereby eliminating the undefined from the resulting inferred type. Without the require at the end, num will have number | undefined type.

should fill in defaults without require

Here's an example without require at the end. When doing the addition in the last step, a TypeScript error is produced, because the type is number | undefined:

Object is possibly 'undefined'. ts(2532)


import { compile, v } from 'suretype'

describe('suretype', () => {
  it('should fill in defaults with require', () => {
    expect.assertions(1)

    const schema = v.object({
      num: v.number().default(0).required(),
    })

    const validator = compile(schema, { ensure: true })

    const result = validator({})

    expect(result.num).toStrictEqual(0)
  })

  it('should fill in defaults without require', () => {
    expect.assertions(1)

    const schema = v.object({
      num: v.number().default(0),
    })

    const validator = compile(schema, { ensure: true })

    const result = validator({})

    expect(result.num + 1).toStrictEqual(1)
  })
})

 FAIL  test/valid.test.ts
  suretype
    ✕ should fill in defaults with require (39 ms)
    ✕ should fill in defaults without require (7 ms)

  ● suretype › should fill in defaults with require

    Validation failed

      11 |     const validator = compile(schema, { ensure: true })
      12 |
    > 13 |     const result = validator({})
         |                    ^
      14 |
      15 |     expect(result.num).toStrictEqual(0)
      16 |   })

      at validate (node_modules/suretype/dist/json-schema.js:45:19)
      at Object.<anonymous> (test/valid.test.ts:13:20)

  ● suretype › should fill in defaults with require

    expect.assertions(1)

    Expected one assertion to be called but received zero assertion calls.

      3 | describe('suretype', () => {
      4 |   it('should fill in defaults with require', () => {
    > 5 |     expect.assertions(1)
        |            ^
      6 |
      7 |     const schema = v.object({
      8 |       num: v.number().default(0).required(),

      at Object.<anonymous> (test/valid.test.ts:5:12)

  ● suretype › should fill in defaults without require

    expect(received).toStrictEqual(expected) // deep equality

    Expected: 1
    Received: NaN

      27 |     const result = validator({})
      28 |
    > 29 |     expect(result.num + 1).toStrictEqual(1)
         |                            ^
      30 |   })
      31 | })
      32 |

      at Object.<anonymous> (test/valid.test.ts:29:28)

moltar avatar Oct 23 '21 09:10 moltar

Just realized this can be fixed with the following:

    const validator = compile(schema, { ensure: true, ajvOptions: { useDefaults: true } })

But IMO, there is still a partial issue here.

I would expect the following:

v.number().default(0)

To result a type of number, rather than number | undefined`.

moltar avatar Oct 23 '21 09:10 moltar

Sorry for the late response, the partial issue is still there, and will be fixed by inverting the required/optional feature in the next major version of SureType. useDefaults will become default in v4 too, so you won't need to set that manually.

grantila avatar May 30 '23 19:05 grantila