Skip to content

Commit

Permalink
Merge pull request #24 from VKTRenokh/develop
Browse files Browse the repository at this point in the history
either
  • Loading branch information
VKTRenokh committed Feb 19, 2024
2 parents 8aea720 + cbc401f commit cef2d63
Show file tree
Hide file tree
Showing 28 changed files with 739 additions and 216 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-terms-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@victorenokh/maybe.ts": patch
---

Rename filterOrElse method to ensureOrElse
5 changes: 5 additions & 0 deletions .changeset/rare-mangos-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@victorenokh/maybe.ts": minor
---

Implemented either monad, changed monads structure
5 changes: 5 additions & 0 deletions .changeset/strong-pears-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@victorenokh/maybe.ts": minor
---

Added toMaybe, fromMaybe util functions
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = {
],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/explicit-function-return-type':
'off',
'@typescript-eslint/explicit-module-boundary-types':
Expand Down
155 changes: 8 additions & 147 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,151 +1,12 @@
# Maybe Monad In Typescript
# @victorenokh/maybe.ts

maybe monad implementation in typescript with great types and some utils
# Installation
To install the stable version:
`npm i @victorenokh/maybe.ts`

# Examples
- [Maybe](./examples/maybe.md)
- [Either](./examples/either.md)

## .map()
```ts
maybe(42).map(num => num * 2).map(console.log) // Output: 84
```
## .tap()
``` ts
maybe(42).tap(console.log).map(num => num * 2).tap(console.log) // Output: 42 then 84

```

## .mapNullable()
```ts
const getOrNothing = (num) => num > 2 ? null : num

const a = maybe(4).map(getOrNothing) // type is Maybe<number | null>
const a = maybe(4).mapNullable(getOrNothing) // type is Maybe<number>
```

## .asyncMap()
```ts
const sleep = (ms: number): Promise<number> =>
new Promise((res) => setTimeout(() => res(ms), ms));

maybe(1000)
.asyncMap((ms) => sleep(ms))
.then((maybeTime) => {
maybeTime.map(console.log); // 1000 after 1 second
});
```

## .flatMap()
```ts
maybe(42).flatMap((num) => maybe(num + 5)).map(console.log) // 47

const getNumber = () => Math.random() > 0.5 ? 1 : undefined

maybe(42)
.flatMap((num) =>
undefinedToMaybe(getNumber()).map((secondNum) => secondNum + num),
)
.map(console.log) // 43 or nothing
```

## .equals()
```ts
const a = maybe(24)
const b = maybe(24)
const c = maybe('Hello!')

console.log(a.equals(b)) // true
console.log(a.equals(c)) // false
```


## .getOrElse()
```ts
const value = maybe<string>(null).getOrElse('default string') // value is 'default string'
const value1 = maybe<string>('some string').getOrElse('default string') // value is 'some string'
```

## .flatGetOrElse()
```ts
const value = maybe<number>(null).flatGetOrElse(maybe(42)) // value is 42
const value = maybe(53).flatGetOrElse(maybe(42)) // value is 42
```

## .merge()
```ts
const a = maybe('something')
const b = maybe('something again')

const merged = a.merge(b).map(console.log) // { left: "something", right: "something again" }
```
if something doesn't have value
```ts
const a = maybe<string>(null)
const b = maybe('something again')

const merged = a.merge(b).map(console.log) // nothing happens
```

## undefinedToMaybe()
```ts
const getNumberOrUndefined = () => Math.random() > 0.5 ? 5 : undefined

const number = undefinedToMaybe(getNumberOrUndefined())

number.map(console.log) // 5 or nothing
```

## merge()
```ts
const a = maybe(5)
const b = maybe('hello')
const c = maybe({someKey: 'someValue'})

const merged = merge(a, b, c) // type is Maybe<[number, string, {someKey: 'someValue'}]>

merged.map(console.log) // [5, 'hello', { someKey: 'someValue' }] or if some maybe is nothing, nothing going to happen
```

# mergeMap()
```ts
const add = (a: number, b: number) => a + b

const a = maybe(5)
const b = maybe(100)

const final = mergeMap(a, b, add)

final.map(console.log) // 105 or if some maybe is nothing, nothing going to happen
```

# call()
```ts
const mfn = maybe(() => console.log('hello world'))

mfn.map(call) // hello world
```

# or()
```ts
const a = maybe<number>(null)
const b = maybe(5)
const c = maybe(6)

const final = or(a, b, c)

final.map(console.log) // 5
```

# fromThrowable()
```ts
const throwable = (num: number) => {
if (num > 0.5) {
throw new Error('number is greater than 0.5')
}

return ':)'
}

const something = fromThrowable(throwable)

something(Math.random()).tap(console.log) // :) or nothing
```
# License
The MIT License (MIT)
82 changes: 82 additions & 0 deletions examples/either.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Either Examples
## .map()
```ts
E.right(1)
.map(double)
.fold(() => {}, console.log) // Output: 2
```

## .flatMap()
```ts
const getMoreThan = (
num: number,
): E.Either<string, number> => {
const random = Math.random()

if (random > num) {
return E.left(`random is greater than ${num}`)
}

return E.right(random)
}

getMoreThan(0.5)
.flatMap((num) => getMoreThan(num + 0.01))
.fold(console.error, console.log) // random number, or error in console
```

## .isRight()
```ts
console.log(left('test').isRight()) // Output: false
console.log(right('test').isRight()) // Output: true
```

## .isLeft()
```ts
console.log(left('test').isLeft()) // Output: true
console.log(right('test').isLeft()) // Output: false
```

## .ensureOrElse()
```ts
const user = {
has2Fa: true,
name: '12',
}

const validate = (u: typeof user) => u.has2Fa
const validateName = (u: typeof user) => u.name.length >= 3

const a: Either<string, typeof user> = right(user)

const b = a
.ensureOrElse(validate, () => 'user does not have 2 fa')
.ensureOrElse(
validateName,
() => 'user name is too small',
)

b.fold(
(e) => console.error(e),
(b) => console.log(b),
i) // Output: user name is too small
```

## toMaybe()
```ts
toMaybe(left<string, number>('left')).tap(console.log) // nothing happens
toMaybe(right<number, string>(50)).tap(console.log) // Output: 50
```

## fromMaybe()
```ts
fromMaybe(of(50), 'maybe is nothing').fold(
console.error,
console.log,
) // Output: 50

fromMaybe(none<number>(), 'maybe is nothing').fold(
console.error,
console.log,
) // Output: error maybe is nothing
```
Loading

0 comments on commit cef2d63

Please sign in to comment.