A tiny invariant function for runtime assertions with TypeScript type narrowing
npx @tessl/cli install tessl/npm-tiny-invariant@1.3.00
# Tiny Invariant
1
2
Tiny Invariant is a lightweight assertion library that provides a single `invariant` function for runtime validation with TypeScript type narrowing. It serves as a minimal alternative to the larger invariant library, offering essential assertion functionality with automatic message stripping in production builds for optimal bundle size.
3
4
## Package Information
5
6
- **Package Name**: tiny-invariant
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install tiny-invariant`
10
11
## Core Imports
12
13
```typescript
14
import invariant from "tiny-invariant";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const invariant = require("tiny-invariant");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import invariant from "tiny-invariant";
27
28
// Basic assertion
29
invariant(value, "Expected value to be truthy");
30
31
// Type narrowing example
32
const maybeUser: User | null = getUser();
33
invariant(maybeUser, "Expected user to exist");
34
// maybeUser is now typed as User (null eliminated)
35
36
// Lazy message evaluation
37
invariant(condition, () => getExpensiveErrorMessage());
38
```
39
40
## Capabilities
41
42
### Runtime Assertion
43
44
The core invariant function provides runtime assertion with TypeScript type narrowing capabilities.
45
46
```typescript { .api }
47
/**
48
* Asserts that the condition is truthy, throwing an error if falsy.
49
* In TypeScript, acts as an assertion function to narrow types.
50
* Messages are automatically stripped in production builds.
51
*
52
* @param condition - Value to test for truthiness
53
* @param message - Optional error message or lazy message function
54
* @throws Error when condition is falsy
55
*/
56
function invariant(
57
condition: any,
58
message?: string | (() => string)
59
): asserts condition;
60
```
61
62
**Type Narrowing Behavior:**
63
- Input type can be a union type (e.g., `T | null | undefined`)
64
- After successful assertion, TypeScript narrows the type to exclude falsy possibilities
65
- Acts as a type guard for conditional logic
66
67
**Error Behavior:**
68
- **Development**: Throws `Error("Invariant failed: <message>")` or `Error("Invariant failed")` if no message
69
- **Production**: Always throws `Error("Invariant failed")` (custom messages stripped for bundle size)
70
71
**Message Options:**
72
- String message: `invariant(condition, "Custom error message")`
73
- Lazy function: `invariant(condition, () => computeExpensiveMessage())`
74
- No message: `invariant(condition)` (uses default "Invariant failed")
75
76
**Usage Examples:**
77
78
```typescript
79
// Null checking with type narrowing
80
function processUser(user: User | null) {
81
invariant(user, "User must be provided");
82
// user is now typed as User, not User | null
83
console.log(user.name); // TypeScript knows user is not null
84
}
85
86
// Value validation
87
function divide(a: number, b: number) {
88
invariant(b !== 0, "Division by zero is not allowed");
89
return a / b;
90
}
91
92
// Lazy message for expensive operations
93
function validateConfig(config: unknown) {
94
invariant(
95
isValidConfig(config),
96
() => `Invalid config: ${JSON.stringify(config, null, 2)}`
97
);
98
}
99
100
// Boolean narrowing
101
function handleFlag(flag: boolean) {
102
invariant(flag, "Flag must be true to continue");
103
// TypeScript knows flag is true here
104
}
105
106
// Array/object existence checking
107
function processItems(items: Item[] | undefined) {
108
invariant(items && items.length > 0, "Items array must not be empty");
109
// items is now typed as Item[] (undefined and empty array eliminated)
110
return items.map(processItem);
111
}
112
```
113
114
## Production Optimization
115
116
Tiny Invariant is designed for production optimization:
117
118
- **Message Stripping**: Custom error messages are automatically removed in production builds
119
- **Bundle Size**: Optimized for minimal bundle impact (~217B minified)
120
- **Environment Detection**: Uses `process.env.NODE_ENV` to determine behavior
121
- **Zero Dependencies**: No runtime dependencies
122
123
**Recommended Build Configuration:**
124
125
For optimal production bundles, use build tools that:
126
1. Set `process.env.NODE_ENV` to `"production"`
127
2. Apply dead code elimination/tree shaking
128
3. Use plugins like `babel-plugin-dev-expression` for additional optimization
129
130
## Types
131
132
The package exports a single default function with TypeScript assertion signature:
133
134
```typescript { .api }
135
declare function invariant(
136
condition: any,
137
message?: string | (() => string)
138
): asserts condition;
139
140
export default invariant;
141
```
142
143
**Key Type Features:**
144
- `asserts condition`: TypeScript assertion function signature for type narrowing
145
- `condition: any`: Accepts any value for maximum flexibility
146
- `message?: string | (() => string)`: Optional string or lazy function message
147
- Return type `void` with assertion signature for type narrowing side effects