-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap.test.ts
149 lines (126 loc) · 4.99 KB
/
map.test.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import test from "node:test";
import { ok, equal } from "node:assert/strict";
import { expectType } from "tsd";
import Future from "./index.js";
// The returned Future should inherit the Right and Left types from the FutureLike returned from a callback.
expectType<
<K = never>(futureLike: Future.Like<string, K>) => Future.Self<boolean, K>
>(Future.map((value: string) => Future.of(value === "foo")));
// If error types are different, they have to be united.
expectType<
(
futureLike: Future.Like<number, { foo: string }>,
) => Future.Self<string, Error | { foo: string }>
>(
Future.map((value: number) =>
Future.from<string, Error>((ok, err) =>
Math.random() ? ok(String(value)) : err(new Error()),
),
)<{ foo: string }>,
);
// The returned Future should inherit the Right type from the PromiseLike returned from a callback and the Left type as unknown by default.
expectType<
<K = unknown>(
futureLike: PromiseLike<string>,
) => Future.Self<boolean, unknown>
>(Future.map((value: string) => Promise.resolve(value === "foo")));
// User should be able to type the Left type manually if callback returns the PromiseLike.
expectType<
<K = string>(
promiseLike: PromiseLike<string>,
) => Future.Self<boolean, string | K>
>(
Future.map<string, boolean, string>((value: string) =>
Promise.resolve(value === "foo"),
),
);
// If a callback returns non-thenable value, the returned FutureLike or PromiseLike accepts any Left type.
expectType<<A>(futureLike: Future.Like<number, A>) => Future.Self<number, A>>(
Future.map((number: number) => number + 1),
);
expectType<<A>(futureLike: Future.Like<number, A>) => Future.Self<number, A>>(
Future.map((number: number) => number + 1),
);
// Should unwrap the FutureLike or PromiseLike type if a callback returns mixed types.
expectType<
<A>(futureLike: Future.Like<number, A>) => Future.Self<number | "foo", A>
>(Future.map((value: number) => (Math.random() ? value : Future.of("foo"))));
expectType<
<A>(
futureLike: Future.Like<number, A>,
) => Future.Self<number | "foo", unknown>
>(
Future.map((value: number) =>
Math.random() ? value : Promise.resolve("foo"),
),
);
// If a callback returns a non-thenable and the PromiseLike, there should be ability to manually declare Left type.
expectType<
<A>(
futureLike: Future.Like<number, A>,
) => Future.Self<number | string, A | boolean>
>(
Future.map<number, number | Promise<string>, boolean>((value: number) =>
Math.random() ? value + 1 : Promise.resolve("foo"),
),
);
// The returned Future should inherit the Right and Left types from the FutureLike returned from a callback.
expectType<Future.Self<boolean, never>>(
Future.map(Future.of("baz"), (value) => Future.of(value === "baz")),
);
// The returned Future should inherit the Right type from the PromiseLike returned from a callback and the Left type as unknown by default.
expectType<Future.Self<boolean, unknown>>(
Future.map(Promise.resolve("baz"), (value) =>
Promise.resolve(value === "foo"),
),
);
// User should be able to type the Left type manually if callback returns the PromiseLike.
expectType<Future.Self<boolean, string>>(
Future.map(Promise.resolve("foo"), (value) =>
Promise.resolve(value === "foo"),
),
);
// If a callback returns non-thenable value, the returned FutureLike infers the Left type.
expectType<Future.Self<number, never>>(
Future.map(Future.of(9), (number) => number + 1),
);
// If a callback returns non-thenable value, the returned PromiseLike accepts any Left type.
expectType<Future.Self<number, string>>(
Future.map(Promise.resolve(10), (number) => number + 1),
);
// Should unwrap the FutureLike or PromiseLike type if a callback returns mixed types.
expectType<Future.Self<number | "foo", "bar">>(
Future.map(
Future.spawn<number, "bar">(() => {
if (Math.random()) return 1;
else throw "bar";
}),
(value) => (Math.random() ? value : Future.of("foo")),
),
);
expectType<Future.Self<number | "foo", unknown>>(
Future.map(Promise.resolve(10), (value) =>
Math.random() ? value : Promise.resolve("foo"),
),
);
// If a callback returns a non-thenable and the PromiseLike, there should be ability to manually declare Left type.
expectType<Future.Self<number | string, boolean | "baz">>(
Future.map<number, "baz", number | Promise<string>, boolean>(
Promise.resolve(10),
(value) => (Math.random() ? value + 1 : Promise.resolve("foo")),
),
);
test("map function should transform a resolved value of the Future", async () => {
const a = Future.map(Future.of(1), (n) => n + 1);
return a.then((n) => equal(n, 2));
});
test("map function will unwrap a FutureLike returned by a callback", async () => {
const a = Future.map(Future.of(1), (n) => Future.of(n + 1));
return a.then((n) => equal(n, 2));
});
test("map function can accept the Future later and apply callback on it", async () => {
const a = Future.map((n: number) => n + 1);
ok(!Future.is(a));
ok(typeof a === "function");
return a(Future.of(1)).then((n) => equal(n, 2));
});