https://github.com/ehmicky/switch-functional
Functional switch statement
https://github.com/ehmicky/switch-functional
case default filter function functional functional-programming functional-testing functions javascript library logic logic-programming mapping nodejs select switch switch-case switch-case-statements typescript wrapper
Last synced: about 1 month ago
JSON representation
Functional switch statement
- Host: GitHub
- URL: https://github.com/ehmicky/switch-functional
- Owner: ehmicky
- License: mit
- Created: 2025-05-22T00:49:38.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-05-22T00:52:23.000Z (6 months ago)
- Last Synced: 2025-05-22T01:34:23.218Z (6 months ago)
- Topics: case, default, filter, function, functional, functional-programming, functional-testing, functions, javascript, library, logic, logic-programming, mapping, nodejs, select, switch, switch-case, switch-case-statements, typescript, wrapper
- Language: TypeScript
- Homepage:
- Size: 0 Bytes
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
[](https://www.npmjs.com/package/switch-functional)
[](https://unpkg.com/switch-functional?module)
[](/src/main.ts)
[](https://codecov.io/gh/ehmicky/switch-functional)
[](https://bundlephobia.com/package/switch-functional)
[](https://fosstodon.org/@ehmicky)
[](https://medium.com/@ehmicky)
Functional switch statement.
# Features
- [Deep equality testing](#testing-properties)
- Advanced [testing](#testing-input) and
[manipulation](#returning-dynamic-values)
- Add your own domain-specific [conditions](#custom-conditions) and
[transforms](#custom-transforms)
- [Strictly typed](/src/main.ts)
# Examples
## Basic usage
```js
import switchFunctional from 'switch-functional'
const getUserType = (user) =>
switchFunctional(user.type)
.case('dev', 'developer')
.case(['admin', 'owner'], 'administrator')
.default('unknown')
```
This is equivalent to:
```js
const getUserType = (user) => {
switch (user.type) {
case 'dev': {
return 'developer'
}
case 'admin':
case 'owner': {
return 'administrator'
}
default: {
return 'unknown'
}
}
}
```
## Testing input
```js
const getUserType = (user) =>
switchFunctional(user)
.case(isDeveloper, 'developer')
.case([isAdmin, isOwner], 'admin')
.default('unknown')
```
This is equivalent to:
```js
const getUserType = (user) => {
if (isDeveloper(user)) {
return 'developer'
}
if (isAdmin(user) || isOwner(user)) {
return 'admin'
}
return 'unknown'
}
```
## Testing properties
```js
const getUserType = (user) =>
switchFunctional(user)
// Checks `user.hasDevProjects === true`
.case({ hasDevProjects: true }, 'developer')
// Checks for deep properties
.case({ devProjectsCount: 0, permissions: { admin: true } }, 'admin')
.default('unknown')
```
## Returning dynamic values
```js
const getUserType = (user) =>
switchFunctional(user)
.case(isDeveloper, (user) => user.developerType)
.case(isAdmin, (user) => user.adminType)
.default((user) => user.genericType)
```
## Custom conditions
```js
import { Admin, Developer } from './user-classes.js'
// Augment the `.case()` syntax to support domain-specific conditions.
// In this example, this allows conditions to be user classes.
const mapCondition = (condition) =>
USER_CLASSES.has(condition) ? (user) => user instanceof condition : condition
const USER_CLASSES = new Set([Admin, Developer])
export const customSwitch = (user) => switchFunctional(user, { mapCondition })
```
```js
import { customSwitch } from './custom-switch.js'
import { Admin, Developer } from './user-classes.js'
const getUserType = (user) =>
customSwitch(user)
.case(Developer, 'developer')
.case(Admin, 'admin')
.default('unknown')
```
## Custom transforms
```js
// Augment the `.case()` and `.default()` syntax to support domain-specific
// logic applied on the return values.
// In this example, the return value is kept as is. However, it is logged.
const mapReturnValues = (returnValue) => {
console.log(returnValue)
return returnValue
}
export const customSwitch = (user) =>
switchFunctional(user, { mapReturnValues })
```
```js
import { customSwitch } from './custom-switch.js'
// 'developer', 'admin' or 'unknown' will be logged
const getUserType = (user) =>
customSwitch(user)
.case(isDeveloper, 'developer')
.case(isAdmin, 'admin')
.default('unknown')
```
# Install
```bash
npm install switch-functional
```
This package works in both Node.js >=18.18.0 and
[browsers](https://raw.githubusercontent.com/ehmicky/dev-tasks/main/src/browserslist).
This is an ES module. It must be loaded using
[an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c),
not `require()`. If TypeScript is used, it must be configured to
[output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html),
not CommonJS.
# API
## switchFunctional(input, options?)
`input`: `unknown`\
`options?`: [`Options`](#options)\
_Return value_: [`Switch`](#switchcaseconditions-casereturnvalue)
Functional switch statement. This must be chained with
[`.case()`](#switchcaseconditions-casereturnvalue) statements and end with
[`.default()`](#switchdefaultdefaultreturnvalue).
## Switch.case(conditions, caseReturnValue)
`conditions`: [`Condition | Condition[]`](#conditions)\
`caseReturnValue`: `unknown | (input) => unknown`\
_Return value_: [`Switch`](#switchcaseconditions-casereturnvalue)
If the `input` matches the `conditions`, the final return value will be
`caseReturnValue`.
`caseReturnValue` can optionally be a function taking the `input` as argument.
## Switch.default(defaultReturnValue)
`defaultReturnValue`: `unknown | (input) => unknown`\
_Return value_: `unknown`
If one of the [`.case()`](#switchcaseconditions-casereturnvalue) statements
matched, returns its `caseReturnValue`. Else, returns `defaultReturnValue`.
`defaultReturnValue` can optionally be a function taking the `input` as
argument.
## Conditions
The `conditions` can be:
- Any value, checked for equality with
[`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
- An object containing of subset of properties
- A filtering function taking the `input` as argument and returning a boolean
- A boolean
- An array of the above types, checking if _any_ condition in the array matches
## Options
_Type_: `object`
### mapCondition
_Type_: `(unknown) => Condition`
Function mapping each value passed to
[`.case(value)`](#switchcaseconditions-casereturnvalue) or `.case(value[])`.
Can return any value [condition](#conditions), including a function taking the
`input` as argument. Cannot return an array of conditions.
This allows augmenting the syntax of `.case()` to support domain-specific
[custom conditions](#custom-conditions).
### mapReturnValues
_Type_: `(...unknown[]) => unknown | (input) => unknown`
Function mapping each return value passed to
[`.case(..., caseReturnValue)`](#switchcaseconditions-casereturnvalue) or
[`.default(defaultReturnValue)`](#switchdefaultdefaultreturnvalue).
Can return any value, including a function taking the `input` as argument.
Can have multiple parameters: this allows calling `.case()` and `.default()`
with multiple arguments.
This allows augmenting the syntax of `.case()` and `.default()` to support
domain-specific [custom transforms](#custom-transforms).
# Related projects
- [`modern-errors-switch`](https://github.com/ehmicky/modern-errors-switch):
Execute class-specific logic
# Support
For any question, _don't hesitate_ to [submit an issue on GitHub](../../issues).
Everyone is welcome regardless of personal background. We enforce a
[Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and
inclusive environment.
# Contributing
This project was made with ❤️. The simplest way to give back is by starring and
sharing it online.
If the documentation is unclear or has a typo, please click on the page's `Edit`
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our
[guidelines](CONTRIBUTING.md). Pull requests are welcome!