Unlocking the Power of TypeScript Assertion Functions

What are Assertion Functions?

Assertion functions are a special type of function that checks a given condition and throws an error if it’s not met. They’re similar to type guards, but with a key difference: instead of returning a boolean value, assertion functions throw an error if the condition is not satisfied.

JavaScript-like Assertions

Node.js comes with a built-in assert function that checks a given predicate and throws an AssertionError if it’s false. However, this function has limitations, as it’s only evaluated at runtime and doesn’t provide any type information.

assert(predicate, message)

TypeScript-like Assertions

TypeScript assertion functions take it to the next level by specifying the type predicate in their signature. This allows TypeScript’s code flow analysis to infer properties about the code, making it more powerful and flexible.

function assert(value: T, predicate: (value: T) => boolean): asserts value is T {
  if (!predicate(value)) {
    throw new Error('Assertion failed');
  }
}

Function Declarations and Expressions

Assertion functions can be defined as function declarations or expressions. While function expressions offer more flexibility, they have limitations when it comes to hoisting and usage.

// Function declaration
function assertNonNull(value: T | null): asserts value is T {
  if (value === null) {
    throw new Error('Value is null');
  }
}

// Function expression
const assertNonNull = (value: T | null): asserts value is T => {
  if (value === null) {
    throw new Error('Value is null');
  }
};

Assertion Functions and Type Guards

Assertion functions are similar to type guards, but with a key difference: they throw an error instead of returning a boolean value. This makes them more suitable for expressing invariants on variables.

Assertion Functions without a Type Predicate

Assertion functions can also be used without a type predicate, making them more versatile and powerful. This allows developers to write general-purpose assertion functions that can be used in a variety of contexts.

function assert(condition: boolean, message: string) {
  if (!condition) {
    throw new Error(message);
  }
}

Best Practices and Use Cases

Assertion functions are particularly useful for:

  • Expressing non-nullability: Ensuring that a variable is not null or undefined.
  • Narrowing types: Refining the type of a variable based on certain conditions.
  • Checking conditions on variables: Verifying that a variable meets certain requirements.
  • Improving code readability and maintainability: Making code more expressive and easier to understand.

By following best practices and using assertion functions effectively, developers can write more robust and maintainable code.

Leave a Reply