InlineSwitch: A Flexible Pattern Matching Library for TypeScript
Introduction In modern JavaScript and TypeScript applications, we often need to handle complex conditional logic. Traditional switch statements and if-else chains quickly become unwieldy as complexity grows. That's why I'm excited to introduce InlineSwitch, a tiny yet powerful library that brings pattern matching to JavaScript and TypeScript. The Problem with Traditional Approaches Before we dive into InlineSwitch, let's examine the shortcomings of traditional conditional approaches: Switch Statements switch (value) { case 1: return 'One'; case 2: return 'Two'; case 3: return 'Three'; default: return 'Unknown'; } Switch statements are limited to simple equality checks and require break statements to avoid fall-through issues. They also don't support complex conditions like ranges or custom logic. If-Else Chains if (value === 1) { return 'One'; } else if (value === 2) { return 'Two'; } else if (value === 3) { return 'Three'; } else { return 'Unknown'; } If-else chains are verbose and become hard to read as they grow longer. They're also difficult to maintain when adding or removing conditions. Enter InlineSwitch InlineSwitch is a lightweight pattern matching library that provides a clean, functional approach to conditional logic. It supports: Exact value matching Array membership testing Predicate function testing Default case handling All with concise, readable syntax and full TypeScript support. Installation npm install inlineswitch Basic Usage Here's a simple example of InlineSwitch in action: import { inlineSwitch } from 'inlineswitch'; function getDiscount(userType: string) { return inlineSwitch( userType, [ ['premium', () => 0.2], // 20% discount for premium users ['regular', () => 0.1], // 10% discount for regular users ['new', () => 0.15], // 15% discount for new users ], () => 0.05 // 5% default discount ); } Advanced Pattern Matching InlineSwitch really shines with more complex patterns: Array Matching const fruitCategory = inlineSwitch( 'apple', [ [['apple', 'pear'], () => 'pome'], [['peach', 'plum', 'cherry'], () => 'drupe'], [['grape', 'blueberry'], () => 'berry'], ], () => 'other' ); // Result: 'pome' Predicate Functions const sizeCategory = inlineSwitch( 42, [ [(n) => n 'small'], [(n) => n >= 10 && n 'medium'], [(n) => n >= 100, () => 'large'], ] ); // Result: 'medium' Using the Value Each handler receives the original value, allowing for more dynamic results: const result = inlineSwitch( 15, [ [(n) => n % 3 === 0, (n) => `${n} is divisible by 3`], [(n) => n % 5 === 0, (n) => `${n} is divisible by 5`], [(n) => n % 3 === 0 && n % 5 === 0, (n) => `${n} is divisible by both 3 and 5`], ], (n) => `${n} is not divisible by 3 or 5` ); // Result: '15 is divisible by 5' Type Safety InlineSwitch is fully typed, providing excellent IntelliSense support and catching type errors at compile time: type User = { id: number; type: 'admin' | 'editor' | 'viewer'; }; const permissions = inlineSwitch( user, [ [(u) => u.type === 'admin', () => ['read', 'write', 'delete', 'admin']], [(u) => u.type === 'editor', () => ['read', 'write']], [(u) => u.type === 'viewer', () => ['read']], ] ); Error Prevention InlineSwitch checks for duplicate case values at runtime: // This will throw a DuplicateCaseError inlineSwitch( value, [ [1, () => 'One'], [1, () => 'Also One'], // Duplicate key! ] ); Shorthand Syntax For simple use cases, InlineSwitch provides a more concise API: import { switchValue } from 'inlineswitch'; const color = switchValue( 'red', ['red', () => '#ff0000'], ['green', () => '#00ff00'], ['blue', () => '#0000ff'] ); // Result: '#ff0000' Real-World Examples HTTP Status Code Handling const message = inlineSwitch( statusCode, [ [[200, 201, 204], () => 'Success'], [[400, 401, 403, 404], () => 'Client Error'], [[500, 502, 503, 504], () => 'Server Error'], ], () => 'Unknown Status' ); User Roles and Permissions const userInterface = inlineSwitch( userRole, [ ['admin', () => ], ['manager', () => ], ['employee', () => ], ['guest', () => ], ], () => ); Form Validation const validationError = inlineSwitch( password.length, [ [(len) => len 'Password is too short'], [(len) => len > 64, () => 'Password is too long'], [(len) => len >= 8 && len null], ] ); Performance Considerations InlineSwitch is designed for readability and flexibility rather than raw performance. For simple equality checks where performance is critical, native switch statements mi

Introduction
In modern JavaScript and TypeScript applications, we often need to handle complex conditional logic. Traditional switch
statements and if-else
chains quickly become unwieldy as complexity grows. That's why I'm excited to introduce InlineSwitch, a tiny yet powerful library that brings pattern matching to JavaScript and TypeScript.
The Problem with Traditional Approaches
Before we dive into InlineSwitch, let's examine the shortcomings of traditional conditional approaches:
Switch Statements
switch (value) {
case 1:
return 'One';
case 2:
return 'Two';
case 3:
return 'Three';
default:
return 'Unknown';
}
Switch statements are limited to simple equality checks and require break
statements to avoid fall-through issues. They also don't support complex conditions like ranges or custom logic.
If-Else Chains
if (value === 1) {
return 'One';
} else if (value === 2) {
return 'Two';
} else if (value === 3) {
return 'Three';
} else {
return 'Unknown';
}
If-else chains are verbose and become hard to read as they grow longer. They're also difficult to maintain when adding or removing conditions.
Enter InlineSwitch
InlineSwitch is a lightweight pattern matching library that provides a clean, functional approach to conditional logic. It supports:
- Exact value matching
- Array membership testing
- Predicate function testing
- Default case handling
All with concise, readable syntax and full TypeScript support.
Installation
npm install inlineswitch
Basic Usage
Here's a simple example of InlineSwitch in action:
import { inlineSwitch } from 'inlineswitch';
function getDiscount(userType: string) {
return inlineSwitch(
userType,
[
['premium', () => 0.2], // 20% discount for premium users
['regular', () => 0.1], // 10% discount for regular users
['new', () => 0.15], // 15% discount for new users
],
() => 0.05 // 5% default discount
);
}
Advanced Pattern Matching
InlineSwitch really shines with more complex patterns:
Array Matching
const fruitCategory = inlineSwitch(
'apple',
[
[['apple', 'pear'], () => 'pome'],
[['peach', 'plum', 'cherry'], () => 'drupe'],
[['grape', 'blueberry'], () => 'berry'],
],
() => 'other'
);
// Result: 'pome'
Predicate Functions
const sizeCategory = inlineSwitch(
42,
[
[(n) => n < 10, () => 'small'],
[(n) => n >= 10 && n < 100, () => 'medium'],
[(n) => n >= 100, () => 'large'],
]
);
// Result: 'medium'
Using the Value
Each handler receives the original value, allowing for more dynamic results:
const result = inlineSwitch(
15,
[
[(n) => n % 3 === 0, (n) => `${n} is divisible by 3`],
[(n) => n % 5 === 0, (n) => `${n} is divisible by 5`],
[(n) => n % 3 === 0 && n % 5 === 0, (n) => `${n} is divisible by both 3 and 5`],
],
(n) => `${n} is not divisible by 3 or 5`
);
// Result: '15 is divisible by 5'
Type Safety
InlineSwitch is fully typed, providing excellent IntelliSense support and catching type errors at compile time:
type User = {
id: number;
type: 'admin' | 'editor' | 'viewer';
};
const permissions = inlineSwitch<User, string[]>(
user,
[
[(u) => u.type === 'admin', () => ['read', 'write', 'delete', 'admin']],
[(u) => u.type === 'editor', () => ['read', 'write']],
[(u) => u.type === 'viewer', () => ['read']],
]
);
Error Prevention
InlineSwitch checks for duplicate case values at runtime:
// This will throw a DuplicateCaseError
inlineSwitch(
value,
[
[1, () => 'One'],
[1, () => 'Also One'], // Duplicate key!
]
);
Shorthand Syntax
For simple use cases, InlineSwitch provides a more concise API:
import { switchValue } from 'inlineswitch';
const color = switchValue(
'red',
['red', () => '#ff0000'],
['green', () => '#00ff00'],
['blue', () => '#0000ff']
);
// Result: '#ff0000'
Real-World Examples
HTTP Status Code Handling
const message = inlineSwitch(
statusCode,
[
[[200, 201, 204], () => 'Success'],
[[400, 401, 403, 404], () => 'Client Error'],
[[500, 502, 503, 504], () => 'Server Error'],
],
() => 'Unknown Status'
);
User Roles and Permissions
const userInterface = inlineSwitch(
userRole,
[
['admin', () => <AdminDashboard />],
['manager', () => <ManagerView />],
['employee', () => <EmployeePortal />],
['guest', () => <GuestView />],
],
() => <UnauthorizedView />
);
Form Validation
const validationError = inlineSwitch(
password.length,
[
[(len) => len < 8, () => 'Password is too short'],
[(len) => len > 64, () => 'Password is too long'],
[(len) => len >= 8 && len <= 64, () => null],
]
);
Performance Considerations
InlineSwitch is designed for readability and flexibility rather than raw performance. For simple equality checks where performance is critical, native switch statements might be faster. However, for complex conditional logic, InlineSwitch provides a much cleaner alternative with minimal overhead.
Under the Hood
InlineSwitch uses TypeScript's generic types and type guards to maintain type safety throughout the matching process. Here's a simplified look at the implementation:
function inlineSwitch<T, R>(
value: T,
cases: Array<[Pattern<T>, Handler<T, R>]>,
defaultHandler?: Handler<T, R>
): R | undefined {
const matchedCase = cases.find(([pattern]) => {
if (Array.isArray(pattern)) {
return pattern.includes(value);
} else if (typeof pattern === 'function') {
return pattern(value);
} else {
return pattern === value;
}
});
return matchedCase ? matchedCase[1](value) : defaultHandler?.(value);
}
Conclusion
InlineSwitch brings pattern matching to JavaScript and TypeScript in a lightweight, type-safe package. By allowing you to express complex conditional logic clearly and concisely, it helps make your code more maintainable and easier to reason about.
For simple equality checks, it's as readable as a switch statement, but when you need more complex matching patterns, it scales elegantly where traditional approaches become unwieldy.
Give it a try in your next project, and enjoy the benefits of functional pattern matching in your JavaScript and TypeScript code!
npm install inlineswitch
Resources
Happy coding!