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

Required field in schema gets type 'string | undefined' #184

Open
jwasnoggin opened this issue Jul 28, 2021 · 6 comments
Open

Required field in schema gets type 'string | undefined' #184

jwasnoggin opened this issue Jul 28, 2021 · 6 comments

Comments

@jwasnoggin
Copy link

jwasnoggin commented Jul 28, 2021

I'm trying to validate an input and assign it to a variable of a type that I've defined. All fields are required in the validator. However, when I try to assign the validated input I get this error:

Type 'ObjectFromSchema<{ prop1: { type: "string"; required: true; }; }, never>' is not assignable to type 'Body'.
  Types of property 'prop1' are incompatible.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.ts(2322)

Since the attribute prop1 is required, why is it showing as possibly undefined?

Demonstration code (the error is at the line which says const validBody: Body = body;):

import validator from 'is-my-json-valid';

type Body = { prop1: string };

function validateBody(body: any): Body {
    const bodyValidator = validator({
        type: 'object',
        required: true,
        properties: {
            prop1: {
                type: 'string',
                required: true as true
            }
        }
    });

    if (!bodyValidator(body)) {
        throw new Error('Invalid format: ' + bodyValidator.errors);
    }

    const validBody: Body = body;
    return validBody;
}

This is with is-my-json-valid version 2.20.5 and Typescript version 4.3.5, with "strict": true

@LinusU
Copy link
Collaborator

LinusU commented Jul 29, 2021

Ah, required: true is deprecated, the new way is:

    const bodyValidator = validator({
        type: 'object',
-       required: true,
+       required: ['prop1'],
        properties: {
            prop1: {
                type: 'string',
-               required: true as true
            }
        }
    })

We should update all the examples in the readme!

@jwasnoggin
Copy link
Author

Amazing, that's much better.

Definitely should update the readme!

@jwasnoggin
Copy link
Author

I've now got a similar issue with a slightly more complex validator which has nested objects.

Error:

Type 'ObjectFromSchema<{ StringProp: { type: "string"; }; ObjectProp: { type: "object"; required: string[]; properties: { Label: { type: "string"; }; }; }; }, "StringProp" | "ObjectProp">' is not assignable to type 'Body'.
  The types of 'ObjectProp.Label' are incompatible between these types.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.

Code:

import jsonValidator from 'is-my-json-valid';

type Body = { StringProp: string, ObjectProp: { Label: string } };

function validateBody(body: any): Body {
    const bodyValidator = jsonValidator({
        type: 'object',
        required: ['StringProp', 'ObjectProp'],
        properties: {
            StringProp: { type: 'string' },
            ObjectProp: {
                type: 'object',
                required: ['Label'],
                properties: {
                    Label: { type: 'string' }
                }
            }
        }
    });

    if (!bodyValidator(body)) {
        throw new Error('Invalid format: ' + bodyValidator.errors);
    }

    const validBody: Body = body;
    return validBody;
}

@LinusU
Copy link
Collaborator

LinusU commented Aug 4, 2021

Hmmm, for some reason it seems like the required field on ObjectProp is getting typed as the generic string[] instead of ['Label']...

Could you try to make the following change and see if it fixes it:

    const bodyValidator = jsonValidator({
        type: 'object',
        required: ['StringProp', 'ObjectProp'],
        properties: {
            StringProp: { type: 'string' },
            ObjectProp: {
                type: 'object',
-               required: ['Label'],
+               required: ['Label'] as const,
                properties: {
                    Label: { type: 'string' }
                }
            }
        }
    });

@jwasnoggin
Copy link
Author

Same error message, except that required: string[] is now required: readonly ["Label"]

@jwasnoggin
Copy link
Author

Got it to work using required: ['Label' as const]. I guess that's a reasonable workaround, if not immediately obvious.

Note this also works for objects with multiple properties, eg

{
    type: 'object',
    properties: {
        name: { type: 'string' },
        value: { type: 'number' }
    },
    required: ['name' as const, 'value' as const]
}

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

2 participants