Skip to content

[BUG] wrong validation for optional object with NoCheck #74

@apatrida

Description

@apatrida

The following code:


type Php<T> = T | null | undefined | Transform<typeof emptyArrayIsUndefined>
const emptyArrayIsUndefined = (arr: Array<any> & MaxLen<0>): undefined => undefined;

// Interactive playground! Write in your code and see it getting transpiled on the left!
interface User {
    name: string,
    id: number & Min<10>,
    nested?: Php<{
       foo: string
    }>,
    whatever?: NoCheck<{
        z1: string,
        z2: number
    }>
}

function validate(testValue: User) {
    const [value, errors] = check<User>(testValue);
    if (errors && errors.length > 0) {
       console.log(errors);
    }
}


validate({ name: "abc", id: 4 });
validate({ name: "abc", id: 11 })
validate({ name: "abc", id: 11, nested: [] })
validate({ name: "abc", id: 11, nested: [], whatever: { z1: 'z1value', z99: 99 } })

generates

...
        if (value.whatever !== undefined)
            errors.push("Expected value.whatever to be undefined");

which is incorrect. If you do not make that object optional, it removes all checking for the object:

function validate(testValue) {
    const value = testValue;
    const errors = [];
    if (typeof value !== "object" || value === null)
        errors.push("Expected value to be User");
    else {
        const {
            nested: nested_1
        } = value;
        if (typeof value.name !== "string")
            errors.push("Expected value.name to be a string");
        if (typeof value.id !== "number" || value.id < 10)
            errors.push("Expected value.id to be a number, to be greater than 10");
        if (nested_1 !== undefined && (!Array.isArray(nested_1) || nested_1.length > 0) && nested_1 !== null)
            if (typeof nested_1 !== "object")
                errors.push("Expected value.nested to be undefined | null | array, to have a length less than 0 | object");
            else {
                if (typeof nested_1.foo !== "string")
                    errors.push("Expected value.nested.foo to be a string");
            }
    }

So this is a problem, you want the typescript ability to omit providing that object, but you get the opposite behavior from the validation instead, but the correct typescript type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions