This repository has been archived by the owner on Jan 15, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path01_either.ts
102 lines (90 loc) · 2.2 KB
/
01_either.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* eslint-disable no-console */
/* eslint-disable extra-rules/no-commented-out-code */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { pipe } from "fp-ts/function";
import * as O from "fp-ts/Option";
import * as E from "fp-ts/Either";
/**
* Costruire un Either
*/
E.right(42);
E.left("not 42");
const validatePrice = (price: number): E.Either<string, number> =>
price >= 0 ? E.right(price) : E.left("price cannot be negative");
/**
* Usare gli smart constructor
*/
pipe(
O.some(42),
E.fromOption(() => "cannot handle null-ish values")
);
E.tryCatch(
() => JSON.parse('{"baz":true}'),
exception => new Error()
);
/**
* type narrowing
*/
const fooOrError = E.right("foo");
if (E.isRight(fooOrError)) {
console.log(fooOrError.right);
// @ts-expect-error: left non è definito per Right
console.log(fooOrError.left);
} else {
console.log(fooOrError.left);
// @ts-expect-error: right non è definito per Left
console.log(fooOrError.right);
}
/**
* usare map(), chain() e fold()
*/
const checkMinPrice = (price: number): E.Either<string, number> =>
price >= 10 // arbitrary treshold, just an example
? E.right(price)
: E.left("price cannot be less than 10");
const applyDiscount = (perc: number) => (n: number): number =>
n * (1 - perc / 100);
const toEuro = (n: number): string => `$${n}`;
declare const myPrice: number;
pipe(
myPrice,
validatePrice,
E.map(applyDiscount(23)),
E.chain(checkMinPrice),
E.foldW(reason => new Error(reason), toEuro)
);
/**
* mapLeft()
*/
pipe(
myPrice,
validatePrice,
E.mapLeft(failure => new Error(`Validation error: ${failure}`)),
E.map(applyDiscount)
);
// problema: gestione di errori multipli
pipe(
1, // checkMinPrice fallirà
validatePrice,
E.mapLeft(failure => new Error(failure)),
E.chainW(checkMinPrice),
E.mapLeft(failure => {
// ^^^ Error | string
// failure può arrivare sia da validatePrice che da checkMinPrice
})
);
// soluzione: nested pipe
pipe(
1,
validatePrice,
E.mapLeft(failure => new Error(failure)),
E.chainW(price =>
pipe(
price,
checkMinPrice,
E.mapLeft(failure => {
// ^^^ failure può arrivare SOLO da checkMinPrice
})
)
)
);