typecheck.macro icon indicating copy to clipboard operation
typecheck.macro copied to clipboard

Machine-readable errors

Open lukasluecke opened this issue 4 years ago • 4 comments

Thanks for the new error messages functionality, it's a big improvement over just false 😁

However actually trying to use the returned values is a bit inconvenient (beyond just dumping them to console or outputting them somewhere as-is) 😅

I am trying to generate something like a "diff", to highlight places where the validation failed in the input - so ideally I would need something like a structured representation of where the problems are, and then the raw expected type.

Instead of this:

const errors = [
    [
        "input["configuration"]["catalog"]["categories"][0]["item_color"]",
        undefined,
        "type: string"
    ],
    [
        // the final ["groups"] segment seems to be duplicated,
        // it doesn't exist in the type definition

        // not sure if that's something new or still WIP ;)
        "input["configuration"]["integrations"]["providers"]["example"]["quiz"]["groups"]["groups"]",
        undefined,
        "object↵  where all keys are: ↵    type: string"
    ]
]

I would like to get:

const errors = {
    configuration: {
        catalog: {
            categories: {
                0: {
                    item_color: {value: undefined, expectedType: 'string'}
                }
            }
        },
        integrations: {
            providers: {
                example: {
                    quiz: {
                        groups: {value: undefined, expectedType: '{ [key: string]: string; }'}
                    }
                }
            }
        }
    }
}

The structure transformation could be done afterwards, splitting the path string and transforming it into an object-structure or something. Maybe I could also generate type-definition strings from the IR if I request that as the return value (is that possible from the data we still have in that representation?)

lukasluecke avatar Jun 03 '20 14:06 lukasluecke

So, you can pass the option expectedValueAsIR with the value true to createDetailedValidator.

Then, the expected value will be the "type IR" that is expected at that location.

The path where the error occurs should be relatively easy to parse into an object format, if you choose (all object keys are quoted, array keys are unquoted numbers), it always starts with input.

Let me know if any other functionality would be useful in this regard.

Also can you post the type you are validating? I should fix this duplicated groups bug. This error message functionality is pretty new (although I did write a bunch of tests!), so it's really helpful if whenever you encounter a bug in the error messages, if you report it with the type in question. (There shouldn't be many/any bugs though!)

vedantroy avatar Jun 03 '20 17:06 vedantroy

@vedantroy Okay, I'll try to get something working with that 🙂

The relevant part of my type should be the following:

type Quiz = {
    groups: { [key: string]: string; };
}

lukasluecke avatar Jun 03 '20 17:06 lukasluecke

Hmm... I'll take a look at this.

It would also be helpful to have a bit more detail about what you want from the error messages. I think you can convert the path into a nested JSON object, so I assume that's not the issue. The actual value will always remain as the actual value, so I assume that's not an issue either.

Is there an issue with the current string representation of the expected type? It seems like in your envisioned scenario, the expected type would be still be represented as a string. Do you want the string representation to more closely match Typescript's type signatures? It seems to me like the current string representation of the type provides as much detail as a normal typescript type signature.

vedantroy avatar Jun 03 '20 18:06 vedantroy

@vedantroy No worries - I'll try to see what I can get from the current data and let you know if there are any issues or further feature requests 🙂 I do have a few different use cases I'm trying to solve right now:

  • test cases or debugging, where having the "real" type instead of some type description would be more concise and helpful (e.g. { [key: string]: string; } instead of "object↵ where all keys are: ↵ type: string")
  • user-facing messages, where I might want some kind of i18n of the messages

But overall, I'm happy with how the validation works already - nice job! 🏆

lukasluecke avatar Jun 03 '20 18:06 lukasluecke