Type Safety
Leverage TypeScript for type-safe match expressions!
Basic Type Inference
TypeScript automatically infers types from your usage:
typescript
import { match } from '@anilkumarthakur/match'
// Types are inferred automatically
const result = match('success')
.on('success', () => 'Operation succeeded') // string
.on('error', () => 'Operation failed') // string
.otherwise(() => 'Unknown') // string
// result is inferred as: string
// Types are checked at compile time
const result2 = match(200)
.on(200, () => 'OK')
.on(404, () => 'Not Found')
.otherwise(() => 'Unknown') // All must be strings
// result2 is inferred as: stringExplicit Type Parameters
For complex scenarios, specify types explicitly:
typescript
// Explicit types: match<Subject, Result>
const result = match<number | string, boolean>(42)
.on(42, () => true)
.on('test', () => false)
.otherwise(() => false)Union Types
Match on union types for exhaustiveness:
typescript
type Status = 'pending' | 'active' | 'inactive' | 'deleted'
const getStatusLabel = (status: Status): string => {
return match(status)
.on('pending', () => 'Pending Review')
.on('active', () => 'Active')
.on('inactive', () => 'Inactive')
.on('deleted', () => 'Deleted')
.otherwise(() => 'Unknown') // Never reached, but good practice
}
console.log(getStatusLabel('active')) // "Active"Strict Type Checking
Ensure all cases return the same type:
typescript
// ✅ Good - all returns are strings
const result = match(code)
.on(200, () => 'OK')
.on(404, () => 'Not Found')
.otherwise(() => 'Unknown')
// ❌ Bad - return types don't match
const badResult = match(code)
.on(200, () => 'OK')
.on(404, () => 404) // Type error! Should be string
.otherwise(() => 'Unknown')Handler Types
Use Handler type for handler functions:
typescript
import { match, Handler } from '@anilkumarthakur/match'
// Handler<T> is a function that returns T with no parameters
type ResultHandler = Handler<string> // () => string
const handler: Handler<number> = () => 42
const result = match('test')
.on('test', handler) // ✓ Correctly typed
.otherwise(() => 0)Complex Return Types
Match on values that return objects, arrays, or complex types:
typescript
interface Config {
timeout: number
retries: number
debug: boolean
}
type Environment = 'development' | 'staging' | 'production'
const getConfig = (env: Environment): Config => {
return match(env)
.on('development', () => ({
timeout: 5000,
retries: 1,
debug: true
}))
.on('staging', () => ({
timeout: 10000,
retries: 3,
debug: false
}))
.on('production', () => ({
timeout: 30000,
retries: 5,
debug: false
}))
.otherwise(() => ({
timeout: 5000,
retries: 1,
debug: true
}))
}
// Type-safe usage
const config = getConfig('production')
config.timeout // ✓ number
config.retries // ✓ number
config.debug // ✓ boolean
// config.foo // ✗ Property 'foo' does not existGenerics
Create reusable match patterns with generics:
typescript
// Generic handler function
const createStatusHandler = <T extends string>(status: T, activeStates: readonly T[]): boolean => {
return match(status)
.on(...(activeStates as [T, ...T[]]), () => true)
.otherwise(() => false)
}
type PaymentStatus = 'pending' | 'completed' | 'failed' | 'refunded'
const isPaymentActive: Handler<boolean> = () => {
return createStatusHandler('completed' as PaymentStatus, ['completed', 'pending'] as const)
}
console.log(isPaymentActive()) // trueMatchChain Type
The MatchChain interface defines the API:
typescript
import { match, MatchChain } from '@anilkumarthakur/match'
// MatchChain<Subject, Result>
const chain: MatchChain<string, number> = match<string, number>('test').on('test', () => 42)
// Only allows matching on strings
// chain.on(123, () => 1) // ✗ Type error - 123 is not a string
// Results must be numbers
const result: number = chain.otherwise(() => 0) // ✓Error Handling with Types
Use UnhandledMatchError with type safety:
typescript
import { match, UnhandledMatchError } from '@anilkumarthakur/match'
const getValue = (key: string): string => {
try {
return match(key)
.on('a', () => 'value a')
.on('b', () => 'value b')
.valueOf() // May throw
} catch (error) {
if (error instanceof UnhandledMatchError) {
console.error('Unhandled key:', error.message)
return 'default'
}
throw error // Re-throw other errors
}
}Best Practices
Use Union Types: Define specific types for subjects
typescripttype Status = 'active' | 'inactive' // Better than stringReturn Consistent Types: All handlers should return the same type
typescript.on('case1', () => 'string') .on('case2', () => 'string') // ✓Use
otherwise(): Always provide a default casetypescriptmatch(value) .on('case', () => 'result') .otherwise(() => 'default') // ✓Avoid
any: Let TypeScript infer typestypescriptmatch(value) // ✓ Types inferred // match<any, any>(value) // ✗ AvoidUse Enums or Literals: For better type checking
typescriptenum Status { Active = 'active', Inactive = 'inactive' } const result = match(Status.Active) // ✓ Type-safe
Next Steps
- Examples - See real-world use cases
- API Reference - Complete API documentation