Definitelytyped: [@types/yup] Error definition when catching ValidationError

Created on 8 Jan 2019  路  3Comments  路  Source: DefinitelyTyped/DefinitelyTyped

I _think_ this is an issue but it may well be my TS knowledge letting me down.

When I catch a validation error the definition for the error is incorrect and does not give me access to the properties I expect.

try {
  // yup.boolean().validate(null)
  await yup.boolean().validate(null)  // Updated https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31950#issuecomment-452388726
} catch (error) {
  if (error instanceof ValidationError) {
    // I get here however...
    error; // (local var) error: {}
    error.message // "Property 'message' does not exist on type '{}'"
  }
}

ValidationError is defined in two places, L26 and L295, as a function and an interface respectively.

  • Authors:

    • @dhardtke

    • @vtserman

    • @MoretonBayRC

    • @sseppola

    • @YashdalfTheGray

    • @vincentjames501

    • @robertbullen

Most helpful comment

Ah alright, I see what's happening.

I think the types need to merge the function declaration and the interface that's declared later into a class and then it should work because right now, I think, Typescript is typing the Error as the constructor function ValidationError rather than the interface ValidationError; which is why you're getting the type being evaluated to {}.

I gotta run to work right now but I should have some kind of fix tonight or tomorrow morning.

I also realized that we don't capture isError and formatError, which are static methods on the ValidationError constructor function in the source code, in the types so I'll add that as well.

All 3 comments

Hello!

It seems like you're using validate(), which is an async call, as a synchronous call. If you wanna do that, you'd have to use async/await with it.

async () => {
  try {
    await yup.boolean().validate(null);
  } catch (error) {
    // handle error
  }
}

Alternatively, since it returns a promise, you can also just use the standard .then() and .catch() with it.

yup.boolean().validate(null)
.then(results => {})
.catch(errors => ());

or you can also use validateSync() if you want to continue to use synchronous calls.

Thanks @YashdalfTheGray,

Annoyingly that is an error in my example :) My fault during copy/paste/simplify.

I am seeing the issue using sync, async and promise chain:

function syncTest() {
  try {
    yup.boolean().validateSync("");
  } catch (error) {
    if (error instanceof ValidationError) {
      error.message; // Property 'message' does not exist on type '{}'.
    }
  }
}

async function asyncTest() {
  try {
    await yup.boolean().validate("");
  } catch (error) {
    if (error instanceof ValidationError) {
      error.message; // Property 'message' does not exist on type '{}'.
    }
  }
}

async function promiseTest() {
  return yup
    .boolean()
    .validate("")
    .catch((error) => {
      if (error instanceof ValidationError) {
        error.message; // Property 'message' does not exist on type '{}'.
      }
    });
}

Ah alright, I see what's happening.

I think the types need to merge the function declaration and the interface that's declared later into a class and then it should work because right now, I think, Typescript is typing the Error as the constructor function ValidationError rather than the interface ValidationError; which is why you're getting the type being evaluated to {}.

I gotta run to work right now but I should have some kind of fix tonight or tomorrow morning.

I also realized that we don't capture isError and formatError, which are static methods on the ValidationError constructor function in the source code, in the types so I'll add that as well.

Was this page helpful?
0 / 5 - 0 ratings