import { assert } from"tsafe/assert";declareconstx:number|string;assert(typeof x ==="string");x.toLowerCase(); //<= Here TypeScript knows that x is a string
The classic assert function, it takes a value as input, if the value is falsy it throws or else it does nothing. Functionally it can be summed up to this:
Typewise however, it takes advantage of the asserts condition statement. If you pass a type guard as value TypeScript can make inference on what happens after the assert instruction.
Assertion on types
Assert can also be used to confirm assertion on types.
You can for example test if a type extends another by doing:
import { assert } from"tsafe/assert";typeA="foo"|"bar";typeB="foo"|"bar"|"baz";//You will get red squiggly lines if A does not extend Bassert<A extends B?true:false>;
When the value is falsy assert throws an instance of AssertionError. Assertion error, extends Error and can be imported like this:
import { AssertionError } from"tsafe/assert";
A specific error message can be passed as second argument to the assert function.
import { assert, AssertionError } from"tsafe/assert";try {assert(false,"foo bar baz");} catch (error) {console.log(error instanceofAssertionError); // trueconsole.log(error.message); // Wrong assertion encountered: "foo bar baz"// Access the original messageconsole.log(error.originalMessage); // foo bar baz}
The message can be a string or callback that returns a string. This is useful when the message is costly to create.
import { assert, AssertionError } from"tsafe/assert";let called =false;constgetMessage= () => {// Do some expensive logic called =true;return"foo bar baz"}try {assert(true, getMessage)console.log(called) // false, getMessage has not been called yetassert(false, getMessage);} catch (error) {console.log(called) // true, getMessage has been calledconsole.log(error instanceofAssertionError); // trueconsole.log(error.message); // Wrong assertion encountered: "foo bar baz"}