Customize Assertion Error Messages
How can I add additional context to an assertion error's message?
Instead of trying to provide facilities to fully customize the error message, Moat Maker strives to simply deliver good and helpful error messages. If you feel a particular error message could be improved in some way, please submit an issue and let us know.
That being said, it's still important to provide ways to add additional context to an error. For this reason, two different parameters have been made available to give you this power: at
and errorPrefix
. To show how these behave, let's start with a very simple validator:
const hasUsernameValidator = validator`{ name: string }`;
If we call .assertMatches()
without customizing the error at all, we'll be given the following error message:
// TypeError: Expected <receivedValue>.name to be of
// type "string" but got type "boolean".
hasUsernameValidator.assertMatches({ name: false });
The "errorPrefix" Assert Parameter
Using errorPrefix
, we can add arbitrary information to the start of the error string. Note that the errorPrefix
string provided absolutely must end with a colon.
// TypeError: Error in myConfig.json: Expected
// <receivedValue>.name to be of type "string" but
// got type "boolean".
hasUsernameValidator.assertMatches({ name: false }, {
errorPrefix: 'Error in myConfig.json:',
});
The "at" Assert Parameter
We can also provide a custom at
field to change the default <receivedValue>
text to be whatever we want. This serves two purposes. 1. You can use something more helpful than the extremely generic "receivedValue" text. 2. If you're validating a value that's part of a deeper object structure, you can provide information about the path already taken to get to where you are. This example illustrates both of these use cases.
const configData = {
user: { name: false },
};
// TypeError: Expected <myConfig.json>.user.name to be
// of type "string" but got type "boolean".
hasUsernameValidator.assertMatches(configData.user, {
at: '<myConfig.json>.user',
});
.assertArgs()
For the common scenario of validating user input for your public API, a special .assertArgs()
function is provided that's pre-configured to provide appropriate "prefix" and "at" fields for you. For the most descriptive errors, it's best to use .assertArgs()
with a validator that matches against a tuple with named entries, however, any validator can be used.
function getName(userInfo: { name: string }) {
validator`[userInfo: { name: string }]`
.assertArgs('getName()', arguments);
return userInfo.name;
}
// TypeError: Received invalid "userInfo" argument for getName():
// Expected <1st argument>.name to be of type "string" but got type "boolean".
getName({ name: false });
.assertArgs()
takes two parameters. The first is the name of the function we're validating the input for. Some examples might be "getName()"
, "MyClass.myStaticMethod()"
, "<date instance>.getDay()"
, or whatever descriptive name you can think of to help someone receiving this error know where the issue happened at. The second argument should be the complete list of arguments your input function takes. You can conveniently use the arguments object to accomplish this purpose. If you do not wish to use the arguments object, or if you can not (e.g. because you're using an arrow function which does not support it), you can instead choose to use an alternative pattern, like spreading and destructuring:
function getName(...allArgs: [userInfo: { name: string }]) {
const [userInfo] = allArgs;
validator`[userInfo: { name: string }]`
.assertArgs('getName()', allArgs);
return userInfo.name;
}
What Else Can You Customize?
By default, a TypeError is thrown when an assertion fails. If you need to throw a different error, you can use the errorFactory
parameter. See the API reference for more details.
Last updated