decoders 2.0.0-beta8 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/CHANGELOG.md +67 -20
  2. package/Decoder.d.ts +94 -0
  3. package/Decoder.js +115 -0
  4. package/Decoder.js.flow +286 -0
  5. package/Decoder.mjs +108 -0
  6. package/README.md +122 -1345
  7. package/_utils.d.ts +0 -1
  8. package/_utils.js +51 -68
  9. package/_utils.js.flow +30 -20
  10. package/_utils.mjs +39 -54
  11. package/annotate.js +79 -72
  12. package/annotate.mjs +62 -58
  13. package/format.d.ts +4 -2
  14. package/format.js +64 -74
  15. package/format.js.flow +14 -12
  16. package/format.mjs +58 -68
  17. package/index.d.ts +38 -41
  18. package/index.js +66 -98
  19. package/index.js.flow +39 -58
  20. package/index.mjs +11 -37
  21. package/{core → lib}/_helpers.d.ts +0 -0
  22. package/lib/arrays.d.ts +59 -0
  23. package/lib/arrays.js +97 -0
  24. package/lib/arrays.js.flow +138 -0
  25. package/lib/arrays.mjs +84 -0
  26. package/lib/basics.d.ts +93 -0
  27. package/lib/basics.js +94 -0
  28. package/lib/basics.js.flow +124 -0
  29. package/lib/basics.mjs +75 -0
  30. package/lib/booleans.d.ts +16 -0
  31. package/lib/booleans.js +25 -0
  32. package/lib/booleans.js.flow +22 -0
  33. package/lib/booleans.mjs +15 -0
  34. package/lib/dates.d.ts +15 -0
  35. package/lib/dates.js +28 -0
  36. package/lib/dates.js.flow +40 -0
  37. package/lib/dates.mjs +19 -0
  38. package/lib/json.d.ts +35 -0
  39. package/lib/json.js +33 -0
  40. package/lib/json.js.flow +50 -0
  41. package/lib/json.mjs +18 -0
  42. package/lib/numbers.d.ts +31 -0
  43. package/lib/numbers.js +31 -0
  44. package/lib/numbers.js.flow +48 -0
  45. package/lib/numbers.mjs +21 -0
  46. package/lib/objects.d.ts +76 -0
  47. package/lib/objects.js +161 -0
  48. package/lib/objects.js.flow +238 -0
  49. package/lib/objects.mjs +147 -0
  50. package/lib/strings.d.ts +56 -0
  51. package/lib/strings.js +58 -0
  52. package/lib/strings.js.flow +90 -0
  53. package/lib/strings.mjs +40 -0
  54. package/lib/unions.d.ts +55 -0
  55. package/lib/unions.js +96 -0
  56. package/lib/unions.js.flow +155 -0
  57. package/lib/unions.mjs +83 -0
  58. package/lib/utilities.d.ts +40 -0
  59. package/lib/utilities.js +48 -0
  60. package/lib/utilities.js.flow +65 -0
  61. package/lib/utilities.mjs +37 -0
  62. package/package.json +64 -17
  63. package/result.d.ts +2 -25
  64. package/result.js +9 -90
  65. package/result.js.flow +4 -76
  66. package/result.mjs +5 -71
  67. package/_guard.d.ts +0 -7
  68. package/_guard.js +0 -22
  69. package/_guard.js.flow +0 -20
  70. package/_guard.mjs +0 -15
  71. package/_types.d.ts +0 -13
  72. package/_types.js +0 -1
  73. package/_types.js.flow +0 -20
  74. package/_types.mjs +0 -0
  75. package/core/array.d.ts +0 -5
  76. package/core/array.js +0 -104
  77. package/core/array.js.flow +0 -100
  78. package/core/array.mjs +0 -91
  79. package/core/boolean.d.ts +0 -5
  80. package/core/boolean.js +0 -40
  81. package/core/boolean.js.flow +0 -27
  82. package/core/boolean.mjs +0 -28
  83. package/core/composition.d.ts +0 -14
  84. package/core/composition.js +0 -54
  85. package/core/composition.js.flow +0 -48
  86. package/core/composition.mjs +0 -44
  87. package/core/constants.d.ts +0 -11
  88. package/core/constants.js +0 -65
  89. package/core/constants.js.flow +0 -44
  90. package/core/constants.mjs +0 -46
  91. package/core/date.d.ts +0 -4
  92. package/core/date.js +0 -42
  93. package/core/date.js.flow +0 -38
  94. package/core/date.mjs +0 -28
  95. package/core/describe.d.ts +0 -3
  96. package/core/describe.js +0 -22
  97. package/core/describe.js.flow +0 -17
  98. package/core/describe.mjs +0 -16
  99. package/core/dispatch.d.ts +0 -8
  100. package/core/dispatch.js +0 -58
  101. package/core/dispatch.js.flow +0 -58
  102. package/core/dispatch.mjs +0 -51
  103. package/core/either.d.ts +0 -61
  104. package/core/either.js +0 -113
  105. package/core/either.js.flow +0 -151
  106. package/core/either.mjs +0 -90
  107. package/core/fail.d.ts +0 -3
  108. package/core/fail.js +0 -17
  109. package/core/fail.js.flow +0 -12
  110. package/core/fail.mjs +0 -11
  111. package/core/instanceOf.d.ts +0 -3
  112. package/core/instanceOf.js +0 -15
  113. package/core/instanceOf.js.flow +0 -20
  114. package/core/instanceOf.mjs +0 -8
  115. package/core/json.d.ts +0 -11
  116. package/core/json.js +0 -31
  117. package/core/json.js.flow +0 -28
  118. package/core/json.mjs +0 -15
  119. package/core/lazy.d.ts +0 -3
  120. package/core/lazy.js +0 -16
  121. package/core/lazy.js.flow +0 -15
  122. package/core/lazy.mjs +0 -11
  123. package/core/mapping.d.ts +0 -6
  124. package/core/mapping.js +0 -67
  125. package/core/mapping.js.flow +0 -62
  126. package/core/mapping.mjs +0 -58
  127. package/core/number.d.ts +0 -6
  128. package/core/number.js +0 -36
  129. package/core/number.js.flow +0 -40
  130. package/core/number.mjs +0 -25
  131. package/core/object.d.ts +0 -33
  132. package/core/object.js +0 -190
  133. package/core/object.js.flow +0 -203
  134. package/core/object.mjs +0 -175
  135. package/core/optional.d.ts +0 -5
  136. package/core/optional.js +0 -50
  137. package/core/optional.js.flow +0 -41
  138. package/core/optional.mjs +0 -38
  139. package/core/string.d.ts +0 -10
  140. package/core/string.js +0 -68
  141. package/core/string.js.flow +0 -59
  142. package/core/string.mjs +0 -49
  143. package/core/tuple.d.ts +0 -30
  144. package/core/tuple.js +0 -177
  145. package/core/tuple.js.flow +0 -211
  146. package/core/tuple.mjs +0 -159
package/README.md CHANGED
@@ -1,1361 +1,138 @@
1
- <img alt="Decoders logo" src="./img/logo@2x.png" width="330" height="64" /><br />
1
+ <img alt="Decoders logo" src="./docs/assets/logo@2x.png" style="width: 100%; max-width: 830px; max-height: 248px" width="830" /><br />
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/decoders.svg)](https://www.npmjs.com/package/decoders)
4
4
  [![Build Status](https://github.com/nvie/decoders/workflows/test/badge.svg)](https://github.com/nvie/decoders/actions)
5
5
  [![Coverage Status](https://img.shields.io/coveralls/nvie/decoders/main.svg)](https://coveralls.io/github/nvie/decoders?branch=main)
6
6
  [![Minified Size](https://badgen.net/bundlephobia/minzip/decoders)](https://bundlephobia.com/result?p=decoders)
7
7
 
8
- Elegant and battle-tested validation library for type-safe input data for TypeScript and
9
- Flow. The API is inspired by Elm’s JSON decoders, hence the name.
8
+ Elegant and battle-tested validation library for type-safe input data for
9
+ [TypeScript](https://www.typescriptlang.org/) and [Flow](https://flow.org/).
10
10
 
11
- See https://nvie.com/posts/introducing-decoders/ for an introduction.
11
+ ## Motivation
12
12
 
13
- ## Why?
13
+ Data entering your application from the outside world should not be trusted without
14
+ validation and often is of the `any` type, effectively disabling your type checker around
15
+ input values. It's an industry good practice to validate your expectations right at your
16
+ program's boundaries. This has two benefits: (1) your inputs are getting validated, and
17
+ (2) you can now statically know for sure the shape of the incoming data. **Decoders help
18
+ solve both of these problems at once.**
14
19
 
15
- If you're using Flow or TypeScript to statically typecheck your JavaScript, you'll know
16
- that any data coming from outside your program’s boundaries is essentially untyped and
17
- unsafe. "Decoders" can help to validate and enforce the correct shape of that data.
18
-
19
- For example, imagine your app expects a list of points in an incoming HTTP request:
20
-
21
- ```javascript
22
- {
23
- points: [
24
- { x: 1, y: 2 },
25
- { x: 3, y: 4 },
26
- ],
27
- }
28
- ```
29
-
30
- In order to decode this, you'll have to tell Flow about the expected structure, and use
31
- the decoders to validate at runtime that the free-form data will be in the expected shape.
32
-
33
- ```javascript
34
- type Point = { x: number, y: number };
35
-
36
- type Payload = {
37
- points: Array<Point>,
38
- };
39
- ```
40
-
41
- Here's a decoder that will work for this type:
42
-
43
- ```javascript
44
- import { array, guard, number, object } from 'decoders';
45
-
46
- const point = object({
47
- x: number,
48
- y: number,
49
- });
50
-
51
- const payload = object({
52
- points: array(point),
53
- });
54
-
55
- const payloadGuard = guard(payload);
56
- ```
57
-
58
- And then, you can use it to decode values:
59
-
60
- ```javascript
61
- >>> payloadGuard(1) // throws!
62
- >>> payloadGuard('foo') // throws!
63
- >>> payloadGuard({ // OK!
64
- ... points: [
65
- ... { x: 1, y: 2 },
66
- ... { x: 3, y: 4 },
67
- ... ],
68
- ... })
69
- ```
70
-
71
- ## API
72
-
73
- The decoders package consists of a few building blocks:
74
-
75
- - [Primitives](#primitives)
76
- - [Compositions](#compositions)
77
- - [Building custom decoders](#building-custom-decoders)
78
-
79
- ### Primitives
80
-
81
- <a name="number" href="#number">#</a> <b>number</b>: <i>Decoder&lt;number&gt;</i>
82
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
83
-
84
- Accepts only finite numbers (integer or float values). This means that values like `NaN`,
85
- or positive and negative `Infinity` are not considered valid numbers.
86
-
87
- <!-- prettier-ignore-start -->
88
- ```javascript
89
- const verify = guard(number);
90
-
91
- // 👍
92
- verify(123) === 123;
93
- verify(-3.14) === -3.14;
94
-
95
- // 👎
96
- verify(Infinity); // throws
97
- verify(NaN); // throws
98
- verify('not a number'); // throws
99
- ```
100
- <!-- prettier-ignore-end -->
101
-
102
- ---
103
-
104
- <a name="integer" href="#integer">#</a> <b>integer</b>: <i>Decoder&lt;integer&gt;</i>
105
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
106
-
107
- Like `number`, but only accepts values that are whole numbers.
108
-
109
- <!-- prettier-ignore-start -->
110
- ```javascript
111
- const verify = guard(integer);
112
-
113
- // 👍
114
- verify(123) === 123;
115
-
116
- // 👎
117
- verify(-3.14); // throws
118
- verify(Infinity); // throws
119
- verify(NaN); // throws
120
- verify('not a integer'); // throws
121
- ```
122
- <!-- prettier-ignore-end -->
123
-
124
- ---
125
-
126
- <a name="positiveNumber" href="#positiveNumber">#</a> <b>positiveNumber</b>:
127
- <i>Decoder&lt;number&gt;</i>
128
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
129
-
130
- Accepts only positive finite numbers (integer or float values).
131
-
132
- <!-- prettier-ignore-start -->
133
- ```javascript
134
- const verify = guard(positiveNumber);
135
-
136
- // 👍
137
- verify(123) === 123;
138
-
139
- // 👎
140
- verify(-42); // throws
141
- verify(3.14); // throws
142
- verify(Infinity); // throws
143
- verify(NaN); // throws
144
- verify('not a number'); // throws
145
- ```
146
- <!-- prettier-ignore-end -->
147
-
148
- ---
149
-
150
- <a name="positiveInteger" href="#positiveInteger">#</a> <b>positiveInteger</b>:
151
- <i>Decoder&lt;number&gt;</i>
152
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
153
-
154
- Accepts only positive finite integers.
155
-
156
- <!-- prettier-ignore-start -->
157
- ```javascript
158
- const verify = guard(positiveInteger);
159
-
160
- // 👍
161
- verify(123) === 123;
162
-
163
- // 👎
164
- verify(-3); // throws
165
- verify(3.14); // throws
166
- verify(Infinity); // throws
167
- verify(NaN); // throws
168
- verify('not a number'); // throws
169
- ```
170
- <!-- prettier-ignore-end -->
171
-
172
- ---
173
-
174
- <a name="string" href="#string">#</a> <b>string</b>: <i>Decoder&lt;string&gt;</i>
175
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
176
-
177
- Accepts only string values.
178
-
179
- <!-- prettier-ignore-start -->
180
- ```javascript
181
- const verify = guard(string);
182
-
183
- // 👍
184
- verify('hello world') === 'hello world';
185
- verify('🚀') === '🚀';
186
- verify('') === '';
187
-
188
- // 👎
189
- verify(123); // throws
190
- verify(true); // throws
191
- verify(null); // throws
192
- ```
193
- <!-- prettier-ignore-end -->
194
-
195
- ---
196
-
197
- <a name="nonEmptyString" href="#nonEmptyString">#</a> <b>nonEmptyString</b>:
198
- <i>Decoder&lt;string&gt;</i>
199
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
200
-
201
- Like `string`, but will reject the empty string, or strings containing only whitespace.
202
-
203
- <!-- prettier-ignore-start -->
204
- ```javascript
205
- const verify = guard(nonEmptyString);
206
-
207
- // 👍
208
- verify('hello world') === 'hello world';
209
- verify('🚀') === '🚀';
210
-
211
- // 👎
212
- verify(123); // throws
213
- verify(' '); // throws
214
- verify(''); // throws
215
- ```
216
- <!-- prettier-ignore-end -->
217
-
218
- ---
219
-
220
- <a name="regex" href="#regex">#</a> <b>regex</b>(): <i>Decoder&lt;string&gt;</i>
221
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
222
-
223
- Accepts only string values that match the given regular expression.
224
-
225
- <!-- prettier-ignore-start -->
226
- ```javascript
227
- const verify = guard(regex(/^[0-9][0-9]+$/));
228
-
229
- // 👍
230
- verify('42') === '42';
231
- verify('83401648364738') === '83401648364738';
232
-
233
- // 👎
234
- verify(''); // throws
235
- verify('1'); // throws
236
- verify('foo'); // throws
237
- ```
238
- <!-- prettier-ignore-end -->
239
-
240
- ---
241
-
242
- <a name="email" href="#email">#</a> <b>email</b>: <i>Decoder&lt;string&gt;</i>
243
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
244
-
245
- Accepts only strings that are syntactically valid email addresses. (This will not mean
246
- that the email address actually exist.)
247
-
248
- <!-- prettier-ignore-start -->
249
- ```javascript
250
- const verify = guard(email);
251
-
252
- // 👍
253
- verify('alice@acme.org') === 'alice@acme.org';
254
-
255
- // 👎
256
- verify('foo'); // throws
257
- verify('@acme.org'); // throws
258
- verify('alice @ acme.org'); // throws
259
- ```
260
- <!-- prettier-ignore-end -->
261
-
262
- ---
263
-
264
- <a name="url" href="#url">#</a> <b>url</b>: <i>Decoder&lt;URL&gt;</i>
265
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
266
-
267
- Accepts strings that are valid URLs, returns the value as a URL instance.
268
-
269
- <!-- prettier-ignore-start -->
270
- ```javascript
271
- const verify = guard(url);
272
-
273
- // 👍
274
- verify('http://nvie.com') === new URL('http://nvie.com/');
275
- verify('https://nvie.com') === new URL('https://nvie.com/');
276
- verify('git+ssh://user@github.com/foo/bar.git') === new URL('git+ssh://user@github.com/foo/bar.git');
277
-
278
- // 👎
279
- verify('foo'); // throws
280
- verify('@acme.org'); // throws
281
- verify('alice @ acme.org'); // throws
282
- verify('/search?q=foo'); // throws
283
- ```
284
- <!-- prettier-ignore-end -->
285
-
286
- ---
287
-
288
- <a name="httpsUrl" href="#httpsUrl">#</a> <b>httpsUrl</b>: <i>Decoder&lt;URL&gt;</i>
289
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
290
-
291
- Accepts strings that are valid URLs, but only HTTPS ones. Returns the value as a URL
292
- instance.
293
-
294
- <!-- prettier-ignore-start -->
295
- ```javascript
296
- const verify = guard(httpsUrl);
297
-
298
- // 👍
299
- verify('https://nvie.com:443') === new URL('https://nvie.com/');
300
-
301
- // 👎
302
- verify('http://nvie.com'); // throws, not HTTPS
303
- verify('git+ssh://user@github.com/foo/bar.git'); // throws, not HTTPS
304
- ```
305
- <!-- prettier-ignore-end -->
306
-
307
- **Tip!** If you need to limit URLs to different protocols than HTTP, you can do as the
308
- HTTPS decoder is implemented: as a predicate on top of a regular `url` decoder.
309
-
310
- ```typescript
311
- import { predicate, url } from 'decoders';
312
-
313
- const gitUrl: Decoder<URL> = predicate(
314
- url,
315
- (value) => value.protocol === 'git:',
316
- 'Must be a git:// URL',
317
- );
318
- ```
319
-
320
- ---
321
-
322
- <a name="boolean" href="#boolean">#</a> <b>boolean</b>: <i>Decoder&lt;boolean&gt;</i>
323
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
324
-
325
- Accepts only boolean values.
326
-
327
- <!-- prettier-ignore-start -->
328
- ```javascript
329
- const verify = guard(boolean);
330
-
331
- // 👍
332
- verify(false) === false;
333
- verify(true) === true;
334
-
335
- // 👎
336
- verify(undefined); // throws
337
- verify('hello world'); // throws
338
- verify(123); // throws
339
- ```
340
- <!-- prettier-ignore-end -->
341
-
342
- ---
343
-
344
- <a name="truthy" href="#truthy">#</a> <b>truthy</b>: <i>Decoder&lt;boolean&gt;</i>
345
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
346
-
347
- Accepts any value and will return its "truth" value. Will never reject.
348
-
349
- ```javascript
350
- const verify = guard(truthy);
351
-
352
- // 👍
353
- verify(false) === false;
354
- verify(true) === true;
355
- verify(undefined) === false;
356
- verify('hello world') === true;
357
- verify('false') === true;
358
- verify(0) === false;
359
- verify(1) === true;
360
- verify(null) === false;
361
-
362
- // 👎
363
- // This decoder will never reject an input
364
- ```
365
-
366
- ---
367
-
368
- <a name="numericBoolean" href="#numericBoolean">#</a> <b>numericBoolean</b>:
369
- <i>Decoder&lt;boolean&gt;</i>
370
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
371
-
372
- Accepts only number values, but return their boolean representation.
373
-
374
- <!-- prettier-ignore-start -->
375
- ```javascript
376
- const verify = guard(numericBoolean);
377
-
378
- // 👍
379
- verify(-1) === true;
380
- verify(0) === false;
381
- verify(123) === true;
382
-
383
- // 👎
384
- verify(false); // throws
385
- verify(true); // throws
386
- verify(undefined); // throws
387
- verify('hello'); // throws
388
- ```
389
- <!-- prettier-ignore-end -->
390
-
391
- ---
392
-
393
- <a name="date" href="#date">#</a> <b>date</b>: <i>Decoder&lt;Date&gt;</i>
394
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/date.js 'Source')
395
-
396
- Accepts only JavaScript [Date][date-api] values.
397
-
398
- <!-- prettier-ignore-start -->
399
- ```javascript
400
- const verify = guard(date);
401
- const now = new Date();
402
-
403
- // 👍
404
- verify(now) === now;
405
-
406
- // 👎
407
- verify(123); // throws
408
- verify('hello'); // throws
409
- ```
410
- <!-- prettier-ignore-end -->
411
-
412
- ---
413
-
414
- <a name="iso8601" href="#iso8601">#</a> <b>iso8601</b>: <i>Decoder&lt;Date&gt;</i>
415
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/date.js 'Source')
416
-
417
- Accepts only [ISO8601][iso8601-fmt]-formatted strings. This is very useful for working
418
- with dates in APIs: serialize them as `.toISOString()` when sending, decode them with
419
- `iso8601` when receiving.
420
-
421
- **NOTE:** This decoder accepts _strings_, but returns _Date_ instances.
422
-
423
- <!-- prettier-ignore-start -->
424
- ```javascript
425
- const verify = guard(iso8601);
426
-
427
- // 👍
428
- verify('2020-06-01T12:00:00Z'); // ≈ new Date('2020-06-01T12:00:00Z')
429
-
430
- // 👎
431
- verify('2020-06-01'); // throws
432
- verify('hello'); // throws
433
- verify(123); // throws
434
- verify(new Date()); // throws (does not accept dates)
435
- ```
436
- <!-- prettier-ignore-end -->
437
-
438
- ---
439
-
440
- <a name="null_" href="#null_">#</a> <b>null\_</b>: <i>Decoder&lt;null&gt;</i>
441
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
442
-
443
- Accepts only the literal `null` value.
444
-
445
- <!-- prettier-ignore-start -->
446
- ```javascript
447
- const verify = guard(null_);
448
-
449
- // 👍
450
- verify(null) === null;
451
-
452
- // 👎
453
- verify(false); // throws
454
- verify(undefined); // throws
455
- verify('hello world'); // throws
456
- ```
457
- <!-- prettier-ignore-end -->
458
-
459
- ---
460
-
461
- <a name="undefined_" href="#undefined_">#</a> <b>undefined\_</b>:
462
- <i>Decoder&lt;void&gt;</i>
463
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
464
-
465
- Accepts only the literal `undefined` value.
466
-
467
- <!-- prettier-ignore-start -->
468
- ```javascript
469
- const verify = guard(undefined_);
470
-
471
- // 👍
472
- verify(undefined) === undefined;
473
-
474
- // 👎
475
- verify(null); // throws
476
- verify(false); // throws
477
- verify('hello world'); // throws
478
- ```
479
- <!-- prettier-ignore-end -->
480
-
481
- ---
482
-
483
- <a name="constant" href="#constant">#</a> <b>constant</b><i>&lt;T&gt;</i>(value: T):
484
- <i>Decoder&lt;T&gt;</i>
485
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
486
-
487
- Accepts only the given constant value.
488
-
489
- For TypeScript, use this syntax:
20
+ ## Example
490
21
 
491
22
  ```typescript
492
- constant('something' as const);
493
- constant(42 as const);
494
- ```
495
-
496
- For Flow, use this syntax:
497
-
498
- ```javascript
499
- constant(('something': 'something'));
500
- constant((42: 42));
501
- ```
502
-
503
- Example:
504
-
505
- <!-- prettier-ignore-start -->
506
- ```typescript
507
- const verify = guard(constant('hello' as const));
508
-
509
- // 👍
510
- verify('hello') === 'hello';
511
-
512
- // 👎
513
- verify('this breaks'); // throws
514
- verify(false); // throws
515
- verify(undefined); // throws
516
- ```
517
- <!-- prettier-ignore-end -->
518
-
519
- ---
520
-
521
- <a name="hardcoded" href="#hardcoded">#</a> <b>hardcoded</b><i>&lt;T&gt;</i>(value: T):
522
- <i>Decoder&lt;T&gt;</i>
523
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
524
-
525
- Accepts any input, completely ignores it, and always returns the provided value. This is
526
- useful to manually add extra fields to object decoders.
527
-
528
- <!-- prettier-ignore-start -->
529
- ```javascript
530
- const verify = guard(hardcoded(42));
531
-
532
- // 👍
533
- verify('hello') === 42;
534
- verify(false) === 42;
535
- verify(undefined) === 42;
536
-
537
- // 👎
538
- // This decoder will never reject an input
539
- ```
540
- <!-- prettier-ignore-end -->
541
-
542
- ---
543
-
544
- <a name="fail" href="#fail">#</a> <b>fail</b>(): <i>Decoder&lt;empty&gt;</i>
545
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/fail.js 'Source')
546
-
547
- Rejects all inputs, and always fails with the given error message. May be useful for
548
- explicitly disallowing keys, or for testing purposes.
549
-
550
- <!-- prettier-ignore-start -->
551
- ```javascript
552
- const verify = guard(object({
553
- a: string,
554
- b: optional(fail('Key b has been removed')),
555
- }));
556
-
557
- // 👍
558
- verify({ a: 'foo' }); // ≈ { a: 'foo' };
559
- verify({ a: 'foo', c: 'bar' }); // ≈ { a: 'foo' };
560
-
561
- // 👎
562
- verify({ a: 'foo', b: 'bar' }); // throws
563
- ```
564
- <!-- prettier-ignore-end -->
565
-
566
- ---
567
-
568
- <a name="unknown" href="#unknown">#</a> <b>unknown</b>: <i>Decoder&lt;unknown&gt;</i>
569
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
570
- <a name="mixed" href="#mixed">#</a> <b>unknown</b>: <i>Decoder&lt;mixed&gt;</i>
571
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')<br />
572
-
573
- Accepts any value and returns it unchanged. Useful for situation in which you don't know
574
- or expect a specific type. Of course, the downside is that you won't know the type of the
575
- value statically and you'll have to further refine it yourself.
576
-
577
- (Unknown is called `mixed` in Flow.)
578
-
579
- ```javascript
580
- const verify = guard(mixed);
581
-
582
- // 👍
583
- verify('hello') === 'hello';
584
- verify(false) === false;
585
- verify(undefined) === undefined;
586
- verify([1, 2]) === [1, 2];
587
-
588
- // 👎
589
- // This decoder will never reject an input
590
- ```
591
-
592
- ### Compositions
593
-
594
- Composite decoders are "higher order" decoders that can build new decoders from existing
595
- decoders that can already decode a "subtype". Examples are: if you already have a decoder
596
- for a `Point` (= `Decoder<Point>`), then you can use `array()` to automatically build a
597
- decoder for arrays of points: `array(pointDecoder)`, which will be of type
598
- `Decoder<Array<Point>>`.
599
-
600
- <a name="optional" href="#optional">#</a>
601
- <b>optional</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>): <i>Decoder&lt;T | void&gt;</i>
602
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
603
-
604
- Accepts only the literal value `undefined`, or whatever the given decoder accepts.
605
-
606
- <!-- prettier-ignore-start -->
607
- ```javascript
608
- const verify = guard(optional(string));
609
-
610
- // 👍
611
- verify('hello') === 'hello';
612
- verify(undefined) === undefined;
613
-
614
- // 👎
615
- verify(null); // throws
616
- verify(0); // throws
617
- verify(42); // throws
618
- ```
619
- <!-- prettier-ignore-end -->
620
-
621
- A typical case where `optional` is useful is in decoding objects with optional fields:
23
+ import { array, iso8601, number, object, optional, string } from 'decoders';
24
+
25
+ //
26
+ // Incoming data at runtime
27
+ //
28
+ const externalData = {
29
+ id: 123,
30
+ name: 'Alison Roberts',
31
+ createdAt: '1994-01-11T12:26:37.024Z',
32
+ tags: ['foo', 'bar'],
33
+ };
622
34
 
623
- ```javascript
624
- object({
35
+ //
36
+ // Write the decoder (= what you expect the data to look like)
37
+ //
38
+ const userDecoder = object({
625
39
  id: number,
626
40
  name: string,
627
- address: optional(string),
41
+ createdAt: optional(iso8601),
42
+ tags: array(string),
628
43
  });
629
- ```
630
-
631
- Which will decode to type:
632
-
633
- ```javascript
634
- {
635
- id: number,
636
- name: string,
637
- address?: string,
638
- }
639
- ```
640
-
641
- ---
642
-
643
- <a name="nullable" href="#nullable">#</a>
644
- <b>nullable</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>): <i>Decoder&lt;T | null&gt;</i>
645
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
646
-
647
- Accepts only the literal value `null`, or whatever the given decoder accepts.
648
-
649
- <!-- prettier-ignore-start -->
650
- ```javascript
651
- const verify = guard(nullable(string));
652
-
653
- // 👍
654
- verify('hello') === 'hello';
655
- verify(null) === null;
656
-
657
- // 👎
658
- verify(undefined); // throws
659
- verify(0); // throws
660
- verify(42); // throws
661
- ```
662
- <!-- prettier-ignore-end -->
663
-
664
- ---
665
-
666
- <a name="maybe" href="#maybe">#</a> <b>maybe</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>):
667
- <i>Decoder&lt;?T&gt;</i>
668
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
669
-
670
- Accepts only `undefined`, `null`, or whatever the given decoder accepts.
671
-
672
- <!-- prettier-ignore-start -->
673
- ```javascript
674
- const verify = guard(maybe(string));
675
-
676
- // 👍
677
- verify('hello') === 'hello';
678
- verify(null) === null;
679
- verify(undefined) === undefined;
680
-
681
- // 👎
682
- verify(0); // throws
683
- verify(42); // throws
684
- ```
685
- <!-- prettier-ignore-end -->
686
-
687
- ---
688
-
689
- <a name="array" href="#array">#</a> <b>array</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>):
690
- <i>Decoder&lt;Array&lt;T&gt;&gt;</i>
691
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/array.js 'Source')
692
-
693
- Accepts only arrays of whatever the given decoder accepts.
694
-
695
- <!-- prettier-ignore-start -->
696
- ```javascript
697
- const verify = guard(array(string));
698
-
699
- // 👍
700
- verify(['hello', 'world']) === ['hello', 'world'];
701
-
702
- // 👎
703
- verify(['hello', 1.2]); // throws
704
- ```
705
- <!-- prettier-ignore-end -->
706
-
707
- ---
708
-
709
- <a name="nonEmptyArray" href="#nonEmptyArray">#</a>
710
- <b>nonEmptyArray</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>):
711
- <i>Decoder&lt;Array&lt;T&gt;&gt;</i>
712
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/array.js 'Source')
713
-
714
- Like `array()`, but will reject arrays with 0 elements.
715
-
716
- <!-- prettier-ignore-start -->
717
- ```javascript
718
- const verify = guard(nonEmptyArray(string));
719
-
720
- // 👍
721
- verify(['hello', 'world']) === ['hello', 'world'];
722
-
723
- // 👎
724
- verify(['hello', 1.2]); // throws
725
- verify([]); // throws
726
- ```
727
- <!-- prettier-ignore-end -->
728
-
729
- ---
730
-
731
- <a name="poja" href="#poja">#</a> <b>poja</b>: <i>Decoder&lt;Array&lt;unknown&gt;&gt;</i>
732
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/array.js 'Source')
733
-
734
- Accepts any array, but doesn't validate its items further.
735
-
736
- "poja" means "plain old JavaScript array", a play on ["pojo"](#pojo).
737
-
738
- <!-- prettier-ignore-start -->
739
- ```javascript
740
- const verify = guard(poja);
741
-
742
- // 👍
743
- verify([1, 'hi', true]) === [1, 'hi', true];
744
- verify(['hello', 'world']) === ['hello', 'world'];
745
- verify([]) === [];
746
-
747
- // 👎
748
- verify({}); // throws
749
- verify('hi'); // throws
750
- ```
751
- <!-- prettier-ignore-end -->
752
-
753
- ---
754
-
755
- <a name="tuple1" href="#tuple1">#</a>
756
- <b>tuple1</b><i>&lt;T1&gt;</i>(<i>Decoder&lt;T1&gt;</i>): <i>Decoder&lt;[T1]&gt;</i>
757
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
758
- <a name="tuple2" href="#tuple2">#</a> <b>tuple2</b><i>&lt;T1,
759
- T2&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>): <i>Decoder&lt;[T1,
760
- T2]&gt;</i>
761
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
762
- <a name="tuple3" href="#tuple3">#</a> <b>tuple3</b><i>&lt;T1, T2,
763
- T3&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>, <i>Decoder&lt;T3&gt;</i>):
764
- <i>Decoder&lt;[T1, T2, T3]&gt;</i>
765
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
766
- <a name="tuple4" href="#tuple4">#</a> <b>tuple4</b><i>&lt;T1, T2, T3,
767
- T4&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>, <i>Decoder&lt;T3&gt;</i>,
768
- <i>Decoder&lt;T4&gt;</i>): <i>Decoder&lt;[T1, T2, T3, T4]&gt;</i>
769
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
770
- <a name="tuple5" href="#tuple5">#</a> <b>tuple5</b><i>&lt;T1, T2, T3, T4,
771
- T5&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>, <i>Decoder&lt;T3&gt;</i>,
772
- <i>Decoder&lt;T3&gt;</i>, <i>Decoder&lt;T4&gt;</i>, <i>Decoder&lt;T5&gt;</i>):
773
- <i>Decoder&lt;[T1, T2, T3, T4, T5]&gt;</i>
774
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
775
- <a name="tuple6" href="#tuple6">#</a> <b>tuple6</b><i>&lt;T1, T2, T3, T4, T5,
776
- T6&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>, <i>Decoder&lt;T3&gt;</i>,
777
- <i>Decoder&lt;T4&gt;</i>, <i>Decoder&lt;T5&gt;</i>, <i>Decoder&lt;T6&gt;</i>):
778
- <i>Decoder&lt;[T1, T2, T3, T4, T5, T6]&gt;</i>
779
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')
780
-
781
- Accepts a _n_-tuple (an array with exactly _n_ items) of values accepted by the _n_ given
782
- decoders.
783
-
784
- <!-- prettier-ignore-start -->
785
- ```javascript
786
- const verify = guard(tuple2(string, number));
787
-
788
- // 👍
789
- verify(['hello', 1.2]) === ['hello', 1.2];
790
-
791
- // 👎
792
- verify([]); // throws, too few items
793
- verify(['hello', 'world']); // throws, not the right types
794
- verify(['a', 1, 'c']); // throws, too many items
795
- ```
796
- <!-- prettier-ignore-end -->
797
-
798
- ---
799
-
800
- <a name="object" href="#object">#</a> <b>object</b><i>&lt;O: { [field: string]:
801
- Decoder&lt;any&gt; }&gt;</i>(mapping: O): <i>Decoder&lt;{ ... }&gt;</i>
802
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
803
-
804
- Accepts object values with fields matching the given decoders. Extra fields that exist on
805
- the input object are ignored and will not be returned.
806
-
807
- <!-- prettier-ignore-start -->
808
- ```javascript
809
- const verify = guard(
810
- object({
811
- x: number,
812
- y: number,
813
- }),
814
- );
815
-
816
- // 👍
817
- verify({ x: 1, y: 2 }) === { x: 1, y: 2 };
818
- verify({ x: 1, y: 2, z: 3 }) === { x: 1, y: 2 }; // ⚠️ extra field `z` not returned!
819
-
820
- // 👎
821
- verify({ x: 1 }); // throws, missing field `y`
822
- ```
823
- <!-- prettier-ignore-end -->
824
-
825
- For more information, see also
826
- [The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
827
-
828
- ---
829
-
830
- <a name="exact" href="#exact">#</a> <b>exact</b><i>&lt;O: { [field: string]:
831
- Decoder&lt;any&gt; }&gt;</i>(mapping: O): <i>Decoder&lt;{ ... }&gt;</i>
832
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
833
-
834
- Like `object()`, but will reject inputs that contain extra keys that are not specified
835
- explicitly.
836
-
837
- <!-- prettier-ignore-start -->
838
- ```javascript
839
- const verify = guard(
840
- exact({
841
- x: number,
842
- y: number,
843
- }),
844
- );
845
-
846
- // 👍
847
- verify({ x: 1, y: 2 }) === { x: 1, y: 2 };
848
-
849
- // 👎
850
- verify({ x: 1, y: 2, z: 3 }); // throws, extra field `z` not allowed
851
- verify({ x: 1 }); // throws, missing field `y`
852
- ```
853
- <!-- prettier-ignore-end -->
854
-
855
- For more information, see also
856
- [The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
857
-
858
- ---
859
-
860
- <a name="inexact" href="#inexact">#</a> <b>inexact</b><i>&lt;O: { [field: string]:
861
- Decoder&lt;any&gt; }&gt;</i>(mapping: O): <i>Decoder&lt;{ ... }&gt;</i>
862
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
863
-
864
- Like `object()`, but will pass through any extra fields on the input object unvalidated
865
- that will thus be of `unknown` type statically.
866
-
867
- <!-- prettier-ignore-start -->
868
- ```javascript
869
- const verify = guard(
870
- inexact({
871
- x: number,
872
- }),
873
- );
874
-
875
- // 👍
876
- verify({ x: 1, y: 2 }) === { x: 1, y: 2 };
877
- verify({ x: 1, y: 2, z: 3 }) === { x: 1, y: 2, z: 3 };
878
-
879
- // 👎
880
- verify({ x: 1 }); // throws, missing field `y`
881
- ```
882
- <!-- prettier-ignore-end -->
883
-
884
- For more information, see also
885
- [The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
886
-
887
- ---
888
-
889
- <a name="pojo" href="#pojo">#</a> <b>pojo</b>: <i>Decoder&lt;{ [key: string]: unknown
890
- }&gt;</i>
891
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
892
-
893
- Accepts any "plain old JavaScript object", but doesn't validate its keys or values
894
- further.
895
-
896
- <!-- prettier-ignore-start -->
897
- ```javascript
898
- const verify = guard(pojo);
899
-
900
- // 👍
901
- verify({}) === {};
902
- verify({ name: 'hi' }) === { name: 'hi' };
903
-
904
- // 👎
905
- verify('hi'); // throws
906
- verify([]); // throws
907
- verify(new Date()); // throws
908
- verify(null); // throws
909
- ```
910
- <!-- prettier-ignore-end -->
911
-
912
- ---
913
-
914
- <a name="dict" href="#dict">#</a> <b>dict</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>):
915
- <i>Decoder&lt;{ [string]: &lt;T&gt;}&gt;</i>
916
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/mapping.js 'Source')
917
-
918
- Accepts objects where all values match the given decoder, and returns the result as a
919
- `{ [string]: T }`.
920
-
921
- The main difference between `object()` and `dict()` is that you'd typically use `object()`
922
- if this is a record-like object, where all field names are known and the values are
923
- heterogeneous. Whereas with `dict()` the keys are typically dynamic and the values
924
- homogeneous, like in a dictionary, a lookup table, or a cache.
925
-
926
- ```javascript
927
- const verify = guard(dict(person)); // Assume you have a "person" decoder already
928
-
929
- // 👍
930
- verify({
931
- 1: { name: 'Alice' },
932
- 2: { name: 'Bob' },
933
- 3: { name: 'Charlie' },
934
- }); // ≈ {
935
- // "1": { name: "Alice" },
936
- // "2": { name: "Bob" },
937
- // "3": { name: "Charlie" },
938
- // }
939
- ```
940
-
941
- ---
942
-
943
- <a name="mapping" href="#mapping">#</a>
944
- <b>mapping</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>): <i>Decoder&lt;Map&lt;string,
945
- T&gt;&gt;</i>
946
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/mapping.js 'Source')
947
-
948
- Like `dict()`, but returns the result as a `Map<string, T>` instead.
949
-
950
- ```javascript
951
- const verify = guard(mapping(person)); // Assume you have a "person" decoder already
952
-
953
- // 👍
954
- verify({
955
- 1: { name: 'Alice' },
956
- 2: { name: 'Bob' },
957
- 3: { name: 'Charlie' },
958
- });
959
- // ≈ Map([
960
- // ['1', { name: 'Alice' }],
961
- // ['2', { name: 'Bob' }],
962
- // ['3', { name: 'Charlie' }],
963
- // ]);
964
- ```
965
-
966
- ---
967
-
968
- <a name="json" href="#json">#</a> <b>json</b>: <i>Decoder&lt;JSONValue&gt;</i>
969
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
970
-
971
- Accepts any value that's a valid JSON value:
972
-
973
- - `null`
974
- - `string`
975
- - `number`
976
- - `boolean`
977
- - `{ [string]: JSONValue }`
978
- - `Array<JSONValue>`
979
-
980
- ```javascript
981
- const verify = guard(json);
982
-
983
- // 👍
984
- verify({
985
- name: 'Amir',
986
- age: 27,
987
- admin: true,
988
- image: null,
989
- tags: ['vip', 'staff'],
990
- });
991
- ```
992
-
993
- Any value returned by `JSON.parse()` should decode without failure.
994
-
995
- ---
996
-
997
- <a name="jsonObject" href="#jsonObject">#</a> <b>jsonObject</b>:
998
- <i>Decoder&lt;JSONObject&gt;</i>
999
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
1000
-
1001
- Like `json`, but will only decode when the JSON value is an object.
1002
-
1003
- <!-- prettier-ignore-start -->
1004
- ```javascript
1005
- const verify = guard(json);
1006
-
1007
- // 👍
1008
- verify({}); // ≈ {}
1009
- verify({ name: 'Amir' }); // ≈ { name: 'Amir' }
1010
-
1011
- // 👎
1012
- verify([]); // throws
1013
- verify([{ name: 'Alice' }]); // throws
1014
- verify('hello'); // throws
1015
- verify(null); // throws
1016
- ```
1017
- <!-- prettier-ignore-end -->
1018
-
1019
- ---
1020
-
1021
- <a name="jsonArray" href="#jsonArray">#</a> <b>jsonArray</b>:
1022
- <i>Decoder&lt;JSONArray&gt;</i>
1023
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
1024
-
1025
- Like `json`, but will only decode when the JSON value is an array.
1026
-
1027
- <!-- prettier-ignore-start -->
1028
- ```javascript
1029
- const verify = guard(json);
1030
-
1031
- // 👍
1032
- verify([]); // ≈ []
1033
- verify([{ name: 'Amir' }]); // ≈ [{ name: 'Amir' }]
1034
-
1035
- // 👎
1036
- verify({}); // throws
1037
- verify({ name: 'Alice' }); // throws
1038
- verify('hello'); // throws
1039
- verify(null); // throws
1040
- ```
1041
- <!-- prettier-ignore-end -->
1042
-
1043
- ---
1044
-
1045
- <a name="either" href="#either">#</a> <b>either</b><i>&lt;T1,
1046
- T2&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>): <i>Decoder&lt;T1 |
1047
- T2&gt;</i><br />
1048
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
1049
- <a name="either2" href="#either2">#</a> <b>either2</b><i>&lt;T1,
1050
- T2&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>): <i>Decoder&lt;T1 |
1051
- T2&gt;</i><br />
1052
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
1053
- <a name="either3" href="#either3">#</a> <b>either3</b><i>&lt;T1, T2,
1054
- T3&gt;</i>(<i>Decoder&lt;T1&gt;</i>, <i>Decoder&lt;T2&gt;</i>, <i>Decoder&lt;T3&gt;</i>):
1055
- <i>Decoder&lt;T1 | T2 | T3&gt;</i>
1056
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
1057
- ...
1058
-
1059
- Accepts any value that is accepted by any of the given decoders. Eithers exist for arities
1060
- up until 9 (`either`, `either3`, `either4`, ..., `either9`).
1061
-
1062
- <!-- prettier-ignore-start -->
1063
- ```javascript
1064
- const verify = guard(either(number, string));
1065
-
1066
- // 👍
1067
- verify('hello world') === 'hello world';
1068
- verify(123) === 123;
1069
-
1070
- // 👎
1071
- verify(false); // throws
1072
- ```
1073
- <!-- prettier-ignore-end -->
1074
-
1075
- ---
1076
-
1077
- <a name="disjointUnion" href="#disjointUnion">#</a> <b>disjointUnion</b><i>&lt;O: {
1078
- [field: string]: (Decoder&lt;T&gt; | Decoder&lt;V&gt; | ...) }&gt;</i>(field: string,
1079
- mapping: O): <i>Decoder&lt;T | V | ...&gt;</i>
1080
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/dispatch.js 'Source')
1081
-
1082
- **NOTE:** In decoders@1.x, this was called `dispatch()`.
1083
-
1084
- Like the `either` family, but only for building unions of object types with a common field
1085
- (like a `type` field) that lets you distinguish members.
1086
-
1087
- The following two decoders are effectively equivalent:
1088
-
1089
- ```javascript
1090
- type Rect = { __type: 'rect', x: number, y: number, width: number, height: number };
1091
- type Circle = { __type: 'circle', cx: number, cy: number, r: number };
1092
- // ^^^^^^
1093
- // Field that defines which decoder to pick
1094
- // vvvvvv
1095
- const shape1: Decoder<Rect | Circle> = disjointUnion('__type', { rect, circle });
1096
- const shape2: Decoder<Rect | Circle> = either(rect, circle);
1097
- ```
1098
-
1099
- But using `disjointUnion()` will typically be more runtime-efficient than using
1100
- `either()`. The reason is that `disjointUnion()` will first do minimal work to "look
1101
- ahead" into the `type` field here, and based on that value, pick which decoder to invoke.
1102
- Error messages will then also be tailored to the specific decoder.
1103
-
1104
- The `either()` version will instead try each decoder in turn until it finds one that
1105
- matches. If none of the alternatives match, it needs to report all errors, which is
1106
- sometimes confusing.
1107
-
1108
- ---
1109
-
1110
- <a name="oneOf" href="#oneOf">#</a> <b>oneOf</b><i>&lt;T&gt;</i>(<i>Array&lt;T&gt;</i>):
1111
- <i>Decoder&lt;T&gt;</i>
1112
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
1113
-
1114
- Accepts any value that is strictly-equal (using `===`) to one of the specified values.
1115
-
1116
- <!-- prettier-ignore-start -->
1117
- ```javascript
1118
- const verify = guard(oneOf(['foo', 'bar', 3]));
1119
-
1120
- // 👍
1121
- verify('foo') === 'foo';
1122
- verify(3) === 3;
1123
-
1124
- // 👎
1125
- verify('hello'); // throws
1126
- verify(4); // throws
1127
- verify(false); // throws
1128
- ```
1129
- <!-- prettier-ignore-end -->
1130
-
1131
- For example, given an array of strings, like so:
1132
-
1133
- ```javascript
1134
- oneOf(['foo', 'bar']);
1135
- ```
1136
-
1137
- TypeScript is capable of inferring the return type as `Decoder<'foo' | 'bar'>`, but in
1138
- Flow it will (unfortunately) be `Decoder<string>`. So in Flow, be sure to explicitly
1139
- annotate the type. Either by doing `oneOf([('foo': 'foo'), ('bar': 'bar')])`, or as
1140
- `oneOf<'foo' | 'bar'>(['foo', 'bar'])`.
1141
-
1142
- ---
1143
-
1144
- <a name="instanceOf" href="#instanceOf">#</a>
1145
- <b>instanceOf</b><i>&lt;T&gt;</i>(<i>Class&lt;T&gt;</i>): <i>Decoder&lt;T&gt;</i>
1146
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/instanceOf.js 'Source')<br />
1147
-
1148
- Accepts any value that is an `instanceof` the given class.
1149
-
1150
- > **NOTE: Help wanted!** The TypeScript annotation for this decoder needs help! If you
1151
- > know how to express it, please submit a PR. See
1152
- > https://github.com/nvie/decoders/blob/main/src/core/instanceOf.d.ts
1153
-
1154
- <!-- prettier-ignore-start -->
1155
- ```javascript
1156
- const verify = guard(instanceOf(Error));
1157
-
1158
- // 👍
1159
- const value = new Error('foo');
1160
- verify(value) === value;
1161
-
1162
- // 👎
1163
- verify('foo'); // throws
1164
- verify(3); // throws
1165
- ```
1166
- <!-- prettier-ignore-end -->
1167
-
1168
- ---
1169
-
1170
- <a name="map" href="#map">#</a> <b>map</b><i>&lt;T, V&gt;</i>(<i>Decoder&lt;T&gt;</i>,
1171
- <i>&lt;T&gt;</i> =&gt; <i>&lt;V&gt;</i>): <i>Decoder&lt;V&gt;</i>
1172
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/utils.js 'Source')<br />
1173
-
1174
- Accepts any value the given decoder accepts, and on success, will call the mapper value
1175
- **on the decoded result**. If the mapper function throws an error, the whole decoder will
1176
- fail using the error message as the failure reason.
1177
-
1178
- <!-- prettier-ignore-start -->
1179
- ```javascript
1180
- const upper = map(string, (s) => s.toUpperCase());
1181
- const verify = guard(upper);
1182
-
1183
- // 👍
1184
- verify('foo') === 'FOO';
1185
-
1186
- // 👎
1187
- verify(4); // throws
1188
- ```
1189
- <!-- prettier-ignore-end -->
1190
-
1191
- ---
1192
-
1193
- <a name="compose" href="#compose">#</a> <b>compose</b><i>&lt;T,
1194
- V&gt;</i>(<i>Decoder&lt;T&gt;</i>, <i>Decoder&lt;V, T&gt;</i>): <i>Decoder&lt;V&gt;</i>
1195
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/composition.js 'Source')<br />
1196
-
1197
- Given a decoder for _T_ and another one for _V_-given-a-_T_. Will first decode the input
1198
- using the first decoder, and _if okay_, pass the result on to the second decoder. The
1199
- second decoder will thus be able to make more assumptions about its input value, i.e. it
1200
- can know what type the input value is (`T` instead of `unknown`).
1201
-
1202
- This is an advanced decoder, typically only useful for authors of decoders. It's not
1203
- recommended to rely on this decoder directly for normal usage.
1204
-
1205
- ---
1206
-
1207
- <a name="predicate" href="#predicate">#</a>
1208
- <b>predicate</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>, <i>&lt;T&gt; => boolean</i>,
1209
- string): <i>Decoder&lt;T&gt;</i>
1210
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/predicate.js 'Source')<br />
1211
-
1212
- Accepts values that are accepted by the decoder _and_ also pass the predicate function.
1213
-
1214
- <!-- prettier-ignore-start -->
1215
- ```typescript
1216
- const odd = predicate(
1217
- number,
1218
- (n) => n % 2 === 1,
1219
- 'Must be odd'
1220
- );
1221
- const verify = guard(odd);
1222
-
1223
- // 👍
1224
- verify(3) === 3;
1225
-
1226
- // 👎
1227
- verify('hi'); // throws: not a number
1228
- verify(42); // throws: not an odd number
1229
- ```
1230
- <!-- prettier-ignore-end -->
1231
-
1232
- In TypeScript, if you provide a predicate that also doubles as a [type
1233
- predicate][type-predicates], then this will be reflected in the return type, too.
1234
-
1235
- ---
1236
-
1237
- <a name="describe" href="#describe">#</a>
1238
- <b>describe</b><i>&lt;T&gt;</i>(<i>Decoder&lt;T&gt;</i>, <i>string</i>):
1239
- <i>Decoder&lt;T&gt;</i>
1240
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/describe.js 'Source')<br />
1241
-
1242
- Uses the given decoder, but will use an alternative error message in case it rejects. This
1243
- can be used to simplify or shorten otherwise long or low-level/technical errors.
1244
-
1245
- ```javascript
1246
- const vowel = describe(
1247
- either5(constant('a'), constant('e'), constant('i'), constant('o'), constant('u')),
1248
- 'Must be vowel',
1249
- );
1250
- ```
1251
-
1252
- ---
1253
-
1254
- <a name="lazy" href="#lazy">#</a> <b>lazy</b><i>&lt;T&gt;</i>(() =>
1255
- <i>Decoder&lt;T&gt;</i>): <i>Decoder&lt;T&gt;</i>
1256
- [&lt;&gt;](https://github.com/nvie/decoders/blob/main/src/core/lazy.js 'Source')<br />
1257
-
1258
- Lazily evaluate the given decoder. This is useful to build self-referential types for
1259
- recursive data structures. Example:
1260
-
1261
- ```js
1262
- type Tree = {
1263
- value: string,
1264
- children: Array<Tree>,
1265
- // ^^^^
1266
- // Self-reference defining a recursive type
1267
- };
1268
-
1269
- const treeDecoder: Decoder<Tree> = object({
1270
- value: string,
1271
- children: array(lazy(() => treeDecoder)),
1272
- // ^^^^^^^^^^^^^^^^^^^^^^^
1273
- // Use lazy() like this to refer to the treeDecoder which is
1274
- // getting defined here
1275
- });
1276
- ```
1277
-
1278
- ### The difference between `object`, `exact`, and `inexact`
1279
-
1280
- The three decoders in the "object" family of decoders only differ in how they treat extra
1281
- properties on input values.
1282
-
1283
- For example, for a definition like:
1284
-
1285
- ```js
1286
- import { exact, inexact, number, object, string } from 'decoders';
1287
-
1288
- const thing = {
1289
- a: string,
1290
- b: number,
1291
- };
1292
- ```
1293
-
1294
- And a runtime input of:
1295
-
1296
- ```js
1297
- {
1298
- a: "hi",
1299
- b: 42,
1300
- c: "extra", // Note "c" is not a known field
1301
- }
1302
- ```
1303
-
1304
- | | Extra properties | Output value | Inferred type |
1305
- | ---------------- | ---------------- | ------------------------------ | ------------------------------------------- |
1306
- | `object(thing)` | discarded | `{a: "hi", b: 42}` | `{a: string, b: number}` |
1307
- | `exact(thing)` | not allowed | ⚡️ Runtime error | `{a: string, b: number}` |
1308
- | `inexact(thing)` | retained | `{a: "hi", b: 42, c: "extra"}` | `{a: string, b: number, [string]: unknown}` |
1309
-
1310
- ### Building custom decoders
1311
-
1312
- There are two main building blocks for defining your own custom decoders: `map()` and
1313
- `compose()`.
1314
-
1315
- There are roughly 3 use cases that you will want to use:
1316
-
1317
- 1. **[Transformation](#transformation)** (i.e. read one type, but return another, or read
1318
- a type but change its value before returning)
1319
- 1. **[Adding extra value requirements](#adding-predicates)** (i.e. decode using an
1320
- existing decoder, but require an extra value check)
1321
- 1. **Chaining** multiple decoders (less common, more advanced)
1322
-
1323
- #### Transformation
1324
-
1325
- To read one type from the input, but return another, use:
1326
-
1327
- ```js
1328
- const numericString: Decoder<number> = map(
1329
- // At runtime, expect to read a string...
1330
- string,
1331
- // ...but return it as a number
1332
- (s) => Number(s),
1333
- );
1334
- ```
1335
-
1336
- To read one type, but change its value before returning:
1337
-
1338
- ```js
1339
- const upperCase: Decoder<string> = map(string, (s) => s.toUpperCase());
1340
- ```
1341
-
1342
- **WARNING:** While you can map anything to anything, it's typically **NOT A GOOD IDEA to
1343
- put too much transformation logic inside decoders**. It's recommended to keep them minimal
1344
- and only try to use them for the most basic use cases, like in the examples above. Keeping
1345
- business logic outside decoders makes them more reusable and composable.
1346
-
1347
- #### Adding predicates
1348
-
1349
- The easiest way to decode using an existing decoder, but enforcing extra runtime checks on
1350
- their values is by wrapping it in a `predicate(...)` construction:
1351
-
1352
- ```js
1353
- const odd = predicate(integer, (n) => n % 2 !== 0, 'Must be odd');
1354
- const shortString = predicate(string, (s) => s.length < 8, 'Must be less than 8 chars');
1355
- ```
1356
44
 
1357
- [date-api]:
1358
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
1359
- [iso8601-fmt]: https://en.wikipedia.org/wiki/ISO_8601
1360
- [type-predicates]:
1361
- https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
45
+ //
46
+ // Call .verify() on the incoming data
47
+ //
48
+ const user = userDecoder.verify(externalData);
49
+ // ^^^^
50
+ // TypeScript can automatically infer this type now:
51
+ //
52
+ // {
53
+ // id: number;
54
+ // name: string;
55
+ // createdAt?: Date;
56
+ // tags: string[];
57
+ // }
58
+ //
59
+ ```
60
+
61
+ ## Documentation
62
+
63
+ <div id="$DecoderType"></div>
64
+ <div id="DecodeResult"></div>
65
+ <div id="Decoder"></div>
66
+ <div id="DecoderType"></div>
67
+ <div id="Guard"></div>
68
+ <div id="JSONArray"></div>
69
+ <div id="JSONObject"></div>
70
+ <div id="JSONValue"></div>
71
+ <div id="Scalar"></div>
72
+ <div id="adding-predicates"></div>
73
+ <div id="always"></div>
74
+ <div id="anyNumber"></div>
75
+ <div id="array"></div>
76
+ <div id="boolean"></div>
77
+ <div id="building-custom-decoders"></div>
78
+ <div id="compose"></div>
79
+ <div id="compositions"></div>
80
+ <div id="constant"></div>
81
+ <div id="date"></div>
82
+ <div id="define"></div>
83
+ <div id="describe"></div>
84
+ <div id="dict"></div>
85
+ <div id="either"></div>
86
+ <div id="email"></div>
87
+ <div id="exact"></div>
88
+ <div id="fail"></div>
89
+ <div id="guard"></div>
90
+ <div id="hardcoded"></div>
91
+ <div id="httpsUrl"></div>
92
+ <div id="inexact"></div>
93
+ <div id="instanceOf"></div>
94
+ <div id="integer"></div>
95
+ <div id="iso8601"></div>
96
+ <div id="json"></div>
97
+ <div id="jsonArray"></div>
98
+ <div id="jsonObject"></div>
99
+ <div id="lazy"></div>
100
+ <div id="mapping"></div>
101
+ <div id="maybe"></div>
102
+ <div id="mixed"></div>
103
+ <div id="never"></div>
104
+ <div id="nonEmptyArray"></div>
105
+ <div id="nonEmptyString"></div>
106
+ <div id="null_"></div>
107
+ <div id="nullable"></div>
108
+ <div id="number"></div>
109
+ <div id="numericBoolean"></div>
110
+ <div id="object"></div>
111
+ <div id="oneOf"></div>
112
+ <div id="optional"></div>
113
+ <div id="poja"></div>
114
+ <div id="pojo"></div>
115
+ <div id="positiveInteger"></div>
116
+ <div id="positiveNumber"></div>
117
+ <div id="predicate"></div>
118
+ <div id="prep"></div>
119
+ <div id="primitives"></div>
120
+ <div id="regex"></div>
121
+ <div id="set"></div>
122
+ <div id="string"></div>
123
+ <div id="taggedUnion"></div>
124
+ <div id="the-difference-between-object-exact-and-inexact"></div>
125
+ <div id="transform"></div>
126
+ <div id="transformation"></div>
127
+ <div id="truthy"></div>
128
+ <div id="tuple"></div>
129
+ <div id="undefined_"></div>
130
+ <div id="unknown"></div>
131
+ <div id="url"></div>
132
+ <div id="uuid"></div>
133
+ <div id="uuidv1"></div>
134
+ <div id="uuidv4"></div>
135
+
136
+ Documentation can be found on [https://decoders.cc](https://decoders.cc).
137
+ (Old v1 documentation can still be found
138
+ [here](https://github.com/nvie/decoders/tree/v1.25.5#readme).)