https://github.com/anderscan/typed-option
Library for working with Options in a type safe manner.
https://github.com/anderscan/typed-option
option typescript
Last synced: 5 months ago
JSON representation
Library for working with Options in a type safe manner.
- Host: GitHub
- URL: https://github.com/anderscan/typed-option
- Owner: AndersCan
- License: mit
- Created: 2017-08-07T16:31:09.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2023-01-05T00:56:28.000Z (almost 3 years ago)
- Last Synced: 2025-04-30T06:08:02.273Z (5 months ago)
- Topics: option, typescript
- Language: TypeScript
- Homepage:
- Size: 1000 KB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# typed-option
[](https://travis-ci.org/AndersCan/typed-option)
[](https://codecov.io/gh/AndersCan/typed-option)
[](https://github.com/prettier/prettier)Library for working with `Option`s in a type safe manner.
## tl;dr
`Option`s makes working with, potentially, `undefined` values more concise and easy to read.**Example**
Given the function:
```javascript
function canFailFn(x: string): string | undefined {
if (Math.random() > 0.5) {
return x
}
return undefined
}
```Turn something like this:
```javascript
let result = 'FAILED'
const a = canFailFn('SUCCESS') // a is string | undefined
if (a) {
const b = canFailFn(a) // b is string | undefined
if (b) {
const c = canFailFn(b) // c is string | undefined
if (c) {
result = c // c is string
}
}
}
console.log(result)
```Into this:
```javascript
import { Option } from 'typed-option'const result2 = Option.from('SUCCESS')
.map(v => canFailFn(v)) // v is of type string.
.map(v => canFailFn(v)) // v is of type string.
.map(v => canFailFn(v)) // v is of type string.
.getOrElse('FAILED')
console.log(result2)// or just
const result3 = Option.from('SUCCESS')
.map(canFailFn)
.map(canFailFn)
.map(canFailFn)
.getOrElse('FAILED')
console.log(result3)
```## Intro
An `Option` is either of type `Some` or `None`.
* **Some** - represents a value of something (a *defined* value)
* **None** - represents a value of nothing (an *undefined* value)In the example above, we start with a `Some('SUCCESS')`. Then we apply the function `canFailFn` multiple times to the value of our `Some`. If the computation fails at any point, we are returned a `None`.
With Options, you do not need to know if you have a `Some` or `None` when applying functions. Only when you need the result do you have to deal with the potential `None` case. This is typically done by calling the `.getOrElse` function (as seen above).
### Unions with undefined
One thing to note is that `undefined` is removed from union types:
```javascript
interface Foo {
a?: number
}
const myFoo: Foo = {
a: 5
}
myFoo.a // 'number | undefined`'
const fooOption = Option.from(myFoo.a) // Option
fooOption.map(a => a) // typeof a is number
```
This means that you will not have to worry about manually testing for `undefined`. A `Some` will never contain an `undefined` value.
## Functions
### Explanation#### Option.from
`Option.from` gives you a `None` for `undefined` values and a `Some` for `defined` values.
```javascript
Option.from(true) // Some(true)
Option.from(false) // Some(false)
Option.from({}) // Some({})
Option.from(0) // Some(0)
Option.from('') // Some('')
Option.from(undefined) // None
```
You can also pass an additional predicate of what a legal value is.
```javascript
Option.from(false, () => true) // Some(false)
Option.from(true, () => false) // None
Option.from(undefined, () => true) // None```
#### do`do` runs a fn on a Option if it is of type `Some`. Similar to `map`, but does not alter/return a new Option.
```javascript
some('world').do(text => console.log(text)) // logs: 'world'
none().do((text) => console.log(text)) // logs:
```#### map
`map` apply a function to a Option if it is of type `Some`
```javascript
some('world').map((text) => "Hello, " + text) // Some('Hello, world')
none().map((text) => "Hello, " + text) // None
```#### flatMap
`flatMap` Same as map, but for when your function returns an Option. `flatMap` will remove the nested option.
```javascript
function getOptionFn(...): Option
const option = ... // Some('Hello, Option')
option.map(getOptionFn) // Some(Some('Hello, Option'))
option.flatMap(getOptionFn) // Some('Hello, Option')
```#### getOrElse
`getOrElse` get the value from a `Some` or return the `else` value for a `None`
```javascript
some(1).getOrElse(() => 999) // 1
none().getOrElse(() => 999) // 999
some(1).getOrElse(999) // 1
none().getOrElse(999) // 999
```
#### orElse`orElse` is the same as `getOrElse`, but `else` returns an Option
```javascript
some(1).orElse(() => Some(999)) // Some(1)
none().orElse(() => Some(999)) // Some(999)
```
#### filter`filter` gives a predicate that a `Some` must hold. If not, returns `None`
```javascript
some(1).filter((v) => false) // None()
some(100).filter((v) => true) // Some(100)
none().filter((v) => true) // None()
```#### match
`match` gives a `pattern matching` looking syntax to work with options.
```javascript
some(1).match({
none: () => 'a none',
some: v => `a Some(${v})`
}) // a Some(1)none().match({
none: () => 'a none',
some: v => `a Some(${v})`
}) // a noneoptionValueIgnored().match({
none: 'failure',
some: `success`
})
```
#### isNone & isSome`isNone` tests if the given `Option` is of type `None`,
`isSome` tests if the given `Option` is of type `Some`
```javascript
const opt1 = ...
if(opt1.isNone()){
// opt1 is None in this block
}
if(opt1.isSome()){
// opt1 is Some in this block
}
```