Skip to content
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

InferType ignores usage of .when in version 1.0.1 and later #2197

Open
Svish opened this issue Apr 9, 2024 · 1 comment
Open

InferType ignores usage of .when in version 1.0.1 and later #2197

Svish opened this issue Apr 9, 2024 · 1 comment

Comments

@Svish
Copy link

Svish commented Apr 9, 2024

Describe the bug

Our schemas are often based on { label: string; value: T } shaped objects, and I've been using when on the object to adjust the validation of the value when its validation depends on other values. This is (as far as I've found) the only way to do this, since value is a child and cannot "see up" and target the values of other sibling objects.

We're also using react-hook-form which has type-checking of field names. These are based on the shape of of the inferred type, so it's important that the inferred shape of the schema is actually correct. E.g. for the field name foo.bar to be type-checked correctly, the inferred shape of the schema needs to contain e.g. { foo: { bar: number } }.

This was all working great in version 1.0.0, but when I tried to upgrade to latest version this week, I found that it's broken now, and seems like it was broken already in version 1.0.1. This prevents us from upgrading, as I'm unable to find a workaround to the issue that allows me to write the schema properly while also getting the expected inferred type structure.

To Reproduce

I've tried to create a sandbox, but not familiar with it and can't figure out how to make a typescript version of it, but reproduction should be very easy. Just paste the following into a typescript-file with yup version 1.0.1 or later:

import { object, string, number, boolean, type InferType } from 'yup';

const s = object({
  number: object({
    label: string().required(),
    value: number().required().min(0),
  }),
  choice: object({
    label: string().required(),
    value: boolean().required(),
  }),
  dependent: object({
    label: string().required(),
  }).when(
    ['choice.value', 'number.value'],
    ([choiceValue, numberValue], schema) => {
      return typeof numberValue === 'number' && choiceValue === true
        ? schema.shape({
            // `value` should be a required number with `numberValue` as max value when `choiceValue` is `true`
            value: number().required().min(0).max(numberValue),
          })
        : schema.shape({
            // `value` should always be `null` when `choiceValue` is `false`
            value: y.number().nullable().transform(() => null),
          });
    }
  ),
});

type V = InferType<typeof s>['dependent']['value'];
//                                        ^^^^^^^
// Property 'value' does not exist on type '{ label: string; }'

The InferType seem to completely ignores the types coming from when, while in version 1.0.0 it would actually come through properly. The { is: true, then: ..., otherwise: ... } variant of .when also have the same issue. This means the type of dependent becomes just { label: string }, instead of { label: string; value: number | undefined | null } which it was in version 1.0.0.

Expected behavior

With yup version 1.0.0 the types coming from .when are picked up properly, and the type of V becomes number | undefined | null, as expected, with no error.

Additional context

We're on Typescript version 5.0.4 right now, but I've tried to upgrade to the latest (5.4.4) just to see if this particular bug would disappear then, but no, seems to only be an issue with yup.

@Svish Svish changed the title Type is no longer inferred correctly when using when InferType ignores usage of .when in version 1.0.1 and later Apr 9, 2024
@Svish
Copy link
Author

Svish commented Apr 9, 2024

I'm guessing the bug was introduced in 60fe3b06f2dde6d1663d444e8eacafc61909b16e, where the types of TThen and TOtherwise seem to have been remove for whatever reason. This change makes it impossible to adjust the members of an object using when, which makes it impossible to adjust validation of object members based on siblings. Or at least I'm unable to see how to do this now. 😕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant