TYPESCRIPT
TypeScript Asserts: Syntax, Usage, and Examples
TypeScript asserts help you enforce type safety by validating values at runtime. They refine types for the TypeScript compiler and prevent unexpected errors in dynamic data handling. Unlike regular type assertions, which only tell the compiler what a value is, assertion functions actively check conditions and throw errors if assumptions don’t hold.
How to Use TypeScript Asserts
An assertion function uses the asserts
keyword to signal to TypeScript that the checked value has a specific type if the function completes successfully. These functions typically throw an error when the condition isn't met.
Basic Syntax of an Assertion Function
function assertString(value: unknown): asserts value is string {
if (typeof value !== "string") {
throw new Error("Value must be a string");
}
}
After calling this function, TypeScript treats value
as a string
within the scope.
function printUpperCase(value: unknown) {
assertString(value);
console.log(value.toUpperCase()); // TypeScript now knows 'value' is a string
}
printUpperCase("hello"); // Output: HELLO
printUpperCase(42); // Throws error: Value must be a string
Using TypeScript Asserts for Objects
To check if an object has a specific property before accessing it, use an assertion function:
function assertKeyExists<T extends object, K extends keyof T>(
obj: T,
key: K
): asserts obj is T & Record<K, unknown> {
if (!(key in obj)) {
throw new Error(`Property ${String(key)} is missing`);
}
}
const user = { name: "Alice", age: 25 };
assertKeyExists(user, "name");
console.log(user.name); // TypeScript now knows 'name' exists
When to Use TypeScript Asserts
TypeScript asserts are useful in situations where type inference isn’t enough or when working with uncertain data. Here are three key scenarios:
- Validating function parameters: Ensure a function receives the correct types, reducing runtime errors.
- Handling dynamic data: Validate API responses, form inputs, or other user-provided values.
- Preventing null or undefined values: Avoid potential issues from missing data by verifying values exist.
Examples of TypeScript Asserts
Asserting a Dictionary Key Exists
When working with dynamic keys in objects or dictionaries, use an assertion function to guarantee safe access:
function assertKeyExists<T>(obj: T, key: keyof T): asserts key is keyof T {
if (!(key in obj)) {
throw new Error(`Key ${String(key)} does not exist`);
}
}
const config: Record<string, string> = { theme: "dark", language: "en" };
assertKeyExists(config, "theme");
console.log(config["theme"]); // Safe access
Ensuring a Value is Not Null
Use a non-null assertion to prevent null
or undefined
values in your code:
function assertNotNull<T>(value: T | null | undefined): asserts value is T {
if (value == null) {
throw new Error("Value cannot be null or undefined");
}
}
const username: string | null = "JohnDoe";
assertNotNull(username);
console.log(username.toUpperCase()); // Safe to use
Using TypeScript Assertion in a Type Guard Function
A type guard function verifies if a value matches a specific type at runtime:
function isNumber(value: unknown): value is number {
return typeof value === "number";
}
function processNumber(value: unknown) {
if (isNumber(value)) {
console.log(value.toFixed(2)); // TypeScript now knows 'value' is a number
} else {
console.log("Not a number");
}
}
processNumber(5.678); // Output: 5.68
processNumber("hello"); // Output: Not a number
Learn More About TypeScript Asserts
TypeScript Assertion vs. Type Guards vs. Assertion Functions
- Type Assertion (
as Type
): Lets you override TypeScript’s type inference but doesn't perform runtime checks. - Type Guards (
is Type
): Checks the type at runtime and refines it within a block. - Assertion Functions (
asserts
): Ensure a condition is met and refine types, throwing an error if the condition fails.
Type Assertion in TypeScript
Type assertions use as
to tell TypeScript that a variable has a specific type:
const input: unknown = "Hello";
const str = input as string;
console.log(str.length); // TypeScript assumes 'str' is a string
This does not validate the type at runtime. If the assumption is incorrect, it may lead to runtime errors.
Double Assertion in TypeScript
A double assertion (as unknown as Type
) can force TypeScript to accept a value as a completely different type. Use this carefully:
const user = { name: "Alice" } as unknown as number;
console.log(user); // Still an object, but TypeScript allows it
Definite Assignment Assertion
The definite assignment assertion (!
) tells TypeScript that a variable will always be assigned before being used:
class UserProfile {
name!: string; // TypeScript won’t complain about missing initialization
setName(name: string) {
this.name = name;
}
}
const user = new UserProfile();
user.setName("Alice");
console.log(user.name); // Safe to access
Using import assert
in TypeScript
You can import assertion functions from external modules for additional safety:
import assert from "assert";
const num = 5;
assert(typeof num === "number", "num should be a number");
Using TypeScript Asserts with Enums
When working with enums, assert values to confirm they match a valid enum entry:
enum Status {
Active = "active",
Inactive = "inactive",
}
function assertStatus(value: any): asserts value is Status {
if (!Object.values(Status).includes(value)) {
throw new Error(`Invalid status: ${value}`);
}
}
const status: string = "active";
assertStatus(status);
console.log(status); // Safe to use as Status
Const Assertion in TypeScript
Using as const
makes an object or array read-only:
const COLORS = ["red", "blue", "green"] as const;
// COLORS.push("yellow"); // Error: Cannot modify a readonly array
console.log(COLORS[0]); // "red"
TypeScript Array Filter Type Guard
Use an assertion function to filter an array while preserving type safety:
function isString(value: unknown): value is string {
return typeof value === "string";
}
const mixedArray: unknown[] = ["hello", 42, "world"];
const stringArray = mixedArray.filter(isString); // Type is now 'string[]'
console.log(stringArray); // Output: ["hello", "world"]
TypeScript asserts add an extra layer of safety by verifying values at runtime. They prevent unexpected errors in applications by ensuring variables conform to expected types. Use them to check function inputs, enforce object properties, and refine types dynamically.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.