A TypeScript-first switch-case utility with object-based and chainable syntax
npm install ts-switch-caseA TypeScript-first control flow utility for modern JavaScript applications, offering a powerful, type-safe alternative to native switch statements. With dual syntax (object-based and chainable), ts-switch-case supports plain values (strings, numbers, symbols), pattern matching, boolean conditions (like switch (true)), and discriminated unions, making it ideal for web, serverless, and API-driven projects.
Inspired by Kotlin's when and Rust's match, ts-switch-case combines conciseness, type safety, and flexibility, outperforming npm alternatives like ts-pattern and switch with its intuitive API and lightweight footprint.
{ 200: 'OK' }) for static mappings or chainable (.case(200, 'OK')) for fluent dynamic logic.'OK') or functions for handlers, supporting strings, numbers, and symbols.p => p > 10) and boolean conditions (switch (true)-style).bash
npm install ts-switch-case
`$3
`typescript
import { switchCase } from 'https://deno.land/x/ts_switch_case@v1.0.0/mod.ts';
`Usage
$3
Map HTTP status codes to messages with concise syntax:
`typescript
import { switchCase } from 'ts-switch-case';
type HttpStatus = 200 | 404 | 500;
const code = 404 as HttpStatus;
const message = switchCase(code, {
200: 'OK',
404: 'Not Found',
500: 'Server Error',
}); // message = 'Not Found'
`$3
Use fluent syntax for the same mapping:
`typescript
const message = switchCase(code)
.case(200, 'OK')
.case(404, 'Not Found')
.case(500, 'Server Error')
.exhaustive(); // message = 'Not Found'
`$3
Handle API response types with type-safe narrowing:
`typescript
type ApiResponse =
| { type: 'success'; data: string }
| { type: 'error'; message: string }
| { type: 'loading' };const response = { type: 'success', data: 'User created' } as ApiResponse;
const result = switchCase(response, 'type', {
success: ({ data }) =>
Success: ${data},
error: ({ message }) => Error: ${message},
loading: () => 'Loading...',
}); // result = 'Success: User created'
`$3
Match scores with custom conditions:
`typescript
const score: number = 85;
const grade = switchCase(
score,
{
excellent: { match: (s) => s >= 90, handler: 'A' },
good: { match: (s) => s >= 80, handler: 'B' },
average: { match: (s) => s >= 70, handler: 'C' },
},
'F'
); // grade = 'B'
`$3
Mimic switch (true) with sequential predicates:
`typescript
const age: number = 25;
const category = switchCase(age)
.case(a => a < 13, 'Child')
.case(a => a < 20, 'Teen')
.case(a => a >= 20, 'Adult')
.default(() => 'Unknown')
.run(); // category = 'Adult'
`$3
Map user roles to permissions:
`typescript
type Role = 'admin' | 'editor' | 'viewer';
const role = 'editor' as Role;
const permissions = switchCase(role, {
admin: ['read', 'write', 'delete'],
editor: ['read', 'write'],
viewer: ['read'],
}); // permissions = ['read', 'write']
`Why ts-switch-case?
Compared to alternatives:
- vs. ts-pattern: More concise object-based syntax for literals and discriminated unions; dual syntax offers flexibility.
- vs. switch: Adds boolean conditions, discriminated unions, symbols, and modern TypeScript.
- vs. switch-case: Supports plain values, type safety, and chainable API.
- vs. Native switch: Returns values, enforces exhaustiveness, and supports advanced matching.Handling Cyclic References
ts-switch-case includes cycle detection via isCyclic and logCyclicError. If a cyclic reference is detected (e.g., in cases or results), an error is thrown with a message pointing to this section.For React applications, cyclic references often occur in
React.ReactNode (e.g., JSX elements with internal fiber properties). To handle this, you can implement a sanitizeNode function to safely process nodes. Example:`typescript
import { isValidElement } from 'react';
import { isCyclic } from 'ts-switch-case';function sanitizeNode(node: React.ReactNode): React.ReactNode {
if (isValidElement(node)) {
const { children, ...safeProps } = node.props;
return { ...node, props: { ...safeProps, children: sanitizeNode(children) } };
}
if (isCyclic(node)) return '[Cyclic Node]';
return node;
}
`Use
sanitizeNode in your switchCase handlers to avoid cyclic errors:`typescript
import { switchCase } from 'ts-switch-case';const node =
Cyclic;
const result = switchCase(node)
.case(v => typeof v === 'string', v => v)
.default(v => sanitizeNode(v))
.run();
`For non-React contexts, use
isCyclic to check inputs and handle cycles appropriately.
Setup for Development
`bash
git clone https://github.com/astralstriker/ts-switch-case.git
cd ts-switch-case
npm install
npm run build
npm test
`Contributing
Contributions are welcome! Please:
1. Fork the repository.
2. Create a feature branch (git checkout -b feature/xyz).
3. Commit changes (git commit -m 'Add feature xyz').
4. Push to the branch (git push origin feature/xyz`).