decoders 2.0.0-beta5 → 2.0.0-beta9

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