decoders 2.0.0-beta4 → 2.0.0-beta8
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.
- package/CHANGELOG.md +10 -0
- package/NotSupportedTSVersion.d.ts +1 -0
- package/README.md +728 -343
- package/_guard.d.ts +7 -0
- package/_guard.js +2 -6
- package/_guard.js.flow +3 -3
- package/{_esm/_guard.js → _guard.mjs} +3 -3
- package/_types.d.ts +13 -0
- package/{_esm/_types.js → _types.mjs} +0 -0
- package/_utils.d.ts +10 -0
- package/{_esm/_utils.js → _utils.mjs} +0 -0
- package/annotate.d.ts +62 -0
- package/{_esm/annotate.js → annotate.mjs} +0 -0
- package/core/_helpers.d.ts +79 -0
- package/core/array.d.ts +5 -0
- package/core/array.js +7 -11
- package/core/array.js.flow +6 -9
- package/{_esm/core/array.js → core/array.mjs} +9 -9
- package/core/boolean.d.ts +5 -0
- package/core/boolean.js +4 -8
- package/core/boolean.js.flow +3 -5
- package/{_esm/core/boolean.js → core/boolean.mjs} +6 -6
- package/core/composition.d.ts +14 -0
- package/core/composition.js +9 -11
- package/core/composition.js.flow +13 -8
- package/{_esm/core/composition.js → core/composition.mjs} +10 -8
- package/core/constants.d.ts +11 -0
- package/core/constants.js +6 -10
- package/core/constants.js.flow +7 -9
- package/{_esm/core/constants.js → core/constants.mjs} +7 -7
- package/core/date.d.ts +4 -0
- package/core/date.js +3 -7
- package/core/date.js.flow +2 -4
- package/{_esm/core/date.js → core/date.mjs} +6 -6
- package/core/describe.d.ts +3 -0
- package/core/describe.js +2 -6
- package/core/describe.js.flow +2 -2
- package/{_esm/core/describe.js → core/describe.mjs} +3 -3
- package/core/dispatch.d.ts +8 -0
- package/core/dispatch.js +9 -13
- package/core/dispatch.js.flow +8 -8
- package/{_esm/core/dispatch.js → core/dispatch.mjs} +10 -10
- package/core/either.d.ts +61 -0
- package/core/either.js +7 -11
- package/core/either.js.flow +6 -6
- package/{_esm/core/either.js → core/either.mjs} +8 -8
- package/core/fail.d.ts +3 -0
- package/core/fail.js +2 -6
- package/core/fail.js.flow +2 -2
- package/{_esm/core/fail.js → core/fail.mjs} +3 -3
- package/core/instanceOf.d.ts +3 -0
- package/core/instanceOf.js +2 -6
- package/core/instanceOf.js.flow +3 -3
- package/core/instanceOf.mjs +8 -0
- package/core/json.d.ts +11 -0
- package/core/json.mjs +15 -0
- package/core/lazy.d.ts +3 -0
- package/{_esm/core/lazy.js → core/lazy.mjs} +0 -0
- package/core/mapping.d.ts +6 -0
- package/core/mapping.js +23 -23
- package/core/mapping.js.flow +25 -17
- package/{_esm/core/mapping.js → core/mapping.mjs} +26 -22
- package/core/number.d.ts +6 -0
- package/core/number.js +9 -13
- package/core/number.js.flow +18 -12
- package/core/number.mjs +25 -0
- package/core/object.d.ts +33 -0
- package/core/object.js +7 -11
- package/core/object.js.flow +7 -7
- package/{_esm/core/object.js → core/object.mjs} +9 -9
- package/core/optional.d.ts +5 -0
- package/core/optional.js +4 -8
- package/core/optional.js.flow +3 -3
- package/{_esm/core/optional.js → core/optional.mjs} +6 -6
- package/core/string.d.ts +10 -0
- package/core/string.js +18 -48
- package/core/string.js.flow +16 -39
- package/core/string.mjs +49 -0
- package/core/tuple.d.ts +30 -0
- package/core/tuple.js +12 -8
- package/core/tuple.js.flow +25 -29
- package/{_esm/core/tuple.js → core/tuple.mjs} +16 -12
- package/format.d.ts +4 -0
- package/{format/inline.js → format.js} +6 -1
- package/{_esm/format/inline.js.flow → format.js.flow} +6 -2
- package/{_esm/format/inline.js → format.mjs} +4 -1
- package/index.d.ts +43 -0
- package/index.js +3 -2
- package/index.js.flow +2 -2
- package/{_esm/index.js → index.mjs} +19 -19
- package/package.json +15 -3
- package/result.d.ts +39 -0
- package/result.js +3 -78
- package/result.js.flow +4 -76
- package/{_esm/result.js → result.mjs} +3 -64
- package/_esm/_guard.js.flow +0 -20
- package/_esm/_types.js.flow +0 -20
- package/_esm/_utils.js.flow +0 -97
- package/_esm/annotate.js.flow +0 -218
- package/_esm/core/array.js.flow +0 -103
- package/_esm/core/boolean.js.flow +0 -29
- package/_esm/core/composition.js.flow +0 -43
- package/_esm/core/constants.js.flow +0 -46
- package/_esm/core/date.js.flow +0 -40
- package/_esm/core/describe.js.flow +0 -17
- package/_esm/core/dispatch.js.flow +0 -58
- package/_esm/core/either.js.flow +0 -151
- package/_esm/core/fail.js.flow +0 -12
- package/_esm/core/instanceOf.js +0 -8
- package/_esm/core/instanceOf.js.flow +0 -20
- package/_esm/core/json.js +0 -15
- package/_esm/core/json.js.flow +0 -28
- package/_esm/core/lazy.js.flow +0 -15
- package/_esm/core/mapping.js.flow +0 -54
- package/_esm/core/number.js +0 -25
- package/_esm/core/number.js.flow +0 -34
- package/_esm/core/object.js.flow +0 -203
- package/_esm/core/optional.js.flow +0 -41
- package/_esm/core/string.js +0 -76
- package/_esm/core/string.js.flow +0 -82
- package/_esm/core/tuple.js.flow +0 -215
- package/_esm/format/index.js +0 -2
- package/_esm/format/index.js.flow +0 -4
- package/_esm/format/short.js +0 -4
- package/_esm/format/short.js.flow +0 -8
- package/_esm/index.js.flow +0 -63
- package/_esm/result.js.flow +0 -170
- package/format/index.js +0 -12
- package/format/index.js.flow +0 -4
- package/format/inline.js.flow +0 -122
- package/format/short.js +0 -10
- package/format/short.js.flow +0 -8
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/decoders)
|
|
4
4
|
[](https://github.com/nvie/decoders/actions)
|
|
5
|
-
[](https://coveralls.io/github/nvie/decoders?branch=main)
|
|
6
6
|
[](https://bundlephobia.com/result?p=decoders)
|
|
7
7
|
|
|
8
8
|
Elegant and battle-tested validation library for type-safe input data for TypeScript and
|
|
@@ -79,220 +79,419 @@ The decoders package consists of a few building blocks:
|
|
|
79
79
|
### Primitives
|
|
80
80
|
|
|
81
81
|
<a name="number" href="#number">#</a> <b>number</b>: <i>Decoder<number></i>
|
|
82
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
82
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
numbers.
|
|
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.
|
|
87
86
|
|
|
87
|
+
<!-- prettier-ignore-start -->
|
|
88
88
|
```javascript
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
94
99
|
```
|
|
100
|
+
<!-- prettier-ignore-end -->
|
|
95
101
|
|
|
96
102
|
---
|
|
97
103
|
|
|
98
104
|
<a name="integer" href="#integer">#</a> <b>integer</b>: <i>Decoder<integer></i>
|
|
99
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
105
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/number.js 'Source')
|
|
100
106
|
|
|
101
|
-
Like `number`, but only
|
|
107
|
+
Like `number`, but only accepts values that are whole numbers.
|
|
102
108
|
|
|
109
|
+
<!-- prettier-ignore-start -->
|
|
103
110
|
```javascript
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
|
109
121
|
```
|
|
122
|
+
<!-- prettier-ignore-end -->
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
<a name="positiveNumber" href="#positiveNumber">#</a> <b>positiveNumber</b>:
|
|
127
|
+
<i>Decoder<number></i>
|
|
128
|
+
[<>](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<number></i>
|
|
152
|
+
[<>](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 -->
|
|
110
171
|
|
|
111
172
|
---
|
|
112
173
|
|
|
113
174
|
<a name="string" href="#string">#</a> <b>string</b>: <i>Decoder<string></i>
|
|
114
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
175
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
|
|
115
176
|
|
|
116
|
-
|
|
177
|
+
Accepts only string values.
|
|
117
178
|
|
|
179
|
+
<!-- prettier-ignore-start -->
|
|
118
180
|
```javascript
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
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
|
|
122
192
|
```
|
|
193
|
+
<!-- prettier-ignore-end -->
|
|
123
194
|
|
|
124
195
|
---
|
|
125
196
|
|
|
126
197
|
<a name="nonEmptyString" href="#nonEmptyString">#</a> <b>nonEmptyString</b>:
|
|
127
198
|
<i>Decoder<string></i>
|
|
128
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
199
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
|
|
129
200
|
|
|
130
|
-
Like `string`, but will
|
|
201
|
+
Like `string`, but will reject the empty string, or strings containing only whitespace.
|
|
131
202
|
|
|
203
|
+
<!-- prettier-ignore-start -->
|
|
132
204
|
```javascript
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
138
215
|
```
|
|
216
|
+
<!-- prettier-ignore-end -->
|
|
139
217
|
|
|
140
218
|
---
|
|
141
219
|
|
|
142
220
|
<a name="regex" href="#regex">#</a> <b>regex</b>(): <i>Decoder<string></i>
|
|
143
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
221
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
|
|
144
222
|
|
|
145
|
-
|
|
146
|
-
expression.
|
|
223
|
+
Accepts only string values that match the given regular expression.
|
|
147
224
|
|
|
225
|
+
<!-- prettier-ignore-start -->
|
|
148
226
|
```javascript
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
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
|
|
152
237
|
```
|
|
238
|
+
<!-- prettier-ignore-end -->
|
|
153
239
|
|
|
154
240
|
---
|
|
155
241
|
|
|
156
242
|
<a name="email" href="#email">#</a> <b>email</b>: <i>Decoder<string></i>
|
|
157
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
243
|
+
[<>](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<URL></i>
|
|
265
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/string.js 'Source')
|
|
158
266
|
|
|
159
|
-
|
|
267
|
+
Accepts strings that are valid URLs, returns the value as a URL instance.
|
|
160
268
|
|
|
269
|
+
<!-- prettier-ignore-start -->
|
|
161
270
|
```javascript
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
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<URL></i>
|
|
289
|
+
[<>](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
|
+
);
|
|
165
318
|
```
|
|
166
319
|
|
|
167
320
|
---
|
|
168
321
|
|
|
169
322
|
<a name="boolean" href="#boolean">#</a> <b>boolean</b>: <i>Decoder<boolean></i>
|
|
170
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
323
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
|
|
171
324
|
|
|
172
|
-
|
|
325
|
+
Accepts only boolean values.
|
|
173
326
|
|
|
327
|
+
<!-- prettier-ignore-start -->
|
|
174
328
|
```javascript
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
|
181
339
|
```
|
|
340
|
+
<!-- prettier-ignore-end -->
|
|
182
341
|
|
|
183
342
|
---
|
|
184
343
|
|
|
185
344
|
<a name="truthy" href="#truthy">#</a> <b>truthy</b>: <i>Decoder<boolean></i>
|
|
186
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
345
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
|
|
187
346
|
|
|
188
|
-
|
|
347
|
+
Accepts any value and will return its "truth" value. Will never reject.
|
|
189
348
|
|
|
190
349
|
```javascript
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
|
200
364
|
```
|
|
201
365
|
|
|
202
366
|
---
|
|
203
367
|
|
|
204
368
|
<a name="numericBoolean" href="#numericBoolean">#</a> <b>numericBoolean</b>:
|
|
205
369
|
<i>Decoder<boolean></i>
|
|
206
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
370
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/boolean.js 'Source')
|
|
207
371
|
|
|
208
|
-
|
|
372
|
+
Accepts only number values, but return their boolean representation.
|
|
209
373
|
|
|
374
|
+
<!-- prettier-ignore-start -->
|
|
210
375
|
```javascript
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
219
388
|
```
|
|
389
|
+
<!-- prettier-ignore-end -->
|
|
220
390
|
|
|
221
391
|
---
|
|
222
392
|
|
|
223
393
|
<a name="date" href="#date">#</a> <b>date</b>: <i>Decoder<Date></i>
|
|
224
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
394
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/date.js 'Source')
|
|
225
395
|
|
|
226
|
-
|
|
227
|
-
[Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
|
|
228
|
-
values.
|
|
396
|
+
Accepts only JavaScript [Date][date-api] values.
|
|
229
397
|
|
|
398
|
+
<!-- prettier-ignore-start -->
|
|
230
399
|
```javascript
|
|
400
|
+
const verify = guard(date);
|
|
231
401
|
const now = new Date();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
402
|
+
|
|
403
|
+
// 👍
|
|
404
|
+
verify(now) === now;
|
|
405
|
+
|
|
406
|
+
// 👎
|
|
407
|
+
verify(123); // throws
|
|
408
|
+
verify('hello'); // throws
|
|
236
409
|
```
|
|
410
|
+
<!-- prettier-ignore-end -->
|
|
237
411
|
|
|
238
412
|
---
|
|
239
413
|
|
|
240
414
|
<a name="iso8601" href="#iso8601">#</a> <b>iso8601</b>: <i>Decoder<Date></i>
|
|
241
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
415
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/date.js 'Source')
|
|
242
416
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
decode them as `iso8601` when receiving.
|
|
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.
|
|
247
420
|
|
|
248
|
-
**NOTE:** This decoder
|
|
421
|
+
**NOTE:** This decoder accepts _strings_, but returns _Date_ instances.
|
|
249
422
|
|
|
423
|
+
<!-- prettier-ignore-start -->
|
|
250
424
|
```javascript
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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)
|
|
256
435
|
```
|
|
436
|
+
<!-- prettier-ignore-end -->
|
|
257
437
|
|
|
258
438
|
---
|
|
259
439
|
|
|
260
440
|
<a name="null_" href="#null_">#</a> <b>null\_</b>: <i>Decoder<null></i>
|
|
261
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
441
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
|
|
262
442
|
|
|
263
|
-
|
|
443
|
+
Accepts only the literal `null` value.
|
|
264
444
|
|
|
445
|
+
<!-- prettier-ignore-start -->
|
|
265
446
|
```javascript
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
|
271
456
|
```
|
|
457
|
+
<!-- prettier-ignore-end -->
|
|
272
458
|
|
|
273
459
|
---
|
|
274
460
|
|
|
275
461
|
<a name="undefined_" href="#undefined_">#</a> <b>undefined\_</b>:
|
|
276
462
|
<i>Decoder<void></i>
|
|
277
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
463
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
|
|
278
464
|
|
|
279
|
-
|
|
465
|
+
Accepts only the literal `undefined` value.
|
|
280
466
|
|
|
467
|
+
<!-- prettier-ignore-start -->
|
|
281
468
|
```javascript
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
|
287
478
|
```
|
|
479
|
+
<!-- prettier-ignore-end -->
|
|
288
480
|
|
|
289
481
|
---
|
|
290
482
|
|
|
291
483
|
<a name="constant" href="#constant">#</a> <b>constant</b><i><T></i>(value: T):
|
|
292
484
|
<i>Decoder<T></i>
|
|
293
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
485
|
+
[<>](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:
|
|
294
490
|
|
|
295
|
-
|
|
491
|
+
```typescript
|
|
492
|
+
constant('something' as const);
|
|
493
|
+
constant(42 as const);
|
|
494
|
+
```
|
|
296
495
|
|
|
297
496
|
For Flow, use this syntax:
|
|
298
497
|
|
|
@@ -303,63 +502,91 @@ constant((42: 42));
|
|
|
303
502
|
|
|
304
503
|
Example:
|
|
305
504
|
|
|
505
|
+
<!-- prettier-ignore-start -->
|
|
306
506
|
```typescript
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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
|
|
312
516
|
```
|
|
517
|
+
<!-- prettier-ignore-end -->
|
|
313
518
|
|
|
314
519
|
---
|
|
315
520
|
|
|
316
521
|
<a name="hardcoded" href="#hardcoded">#</a> <b>hardcoded</b><i><T></i>(value: T):
|
|
317
522
|
<i>Decoder<T></i>
|
|
318
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
523
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
|
|
319
524
|
|
|
320
|
-
|
|
321
|
-
|
|
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.
|
|
322
527
|
|
|
528
|
+
<!-- prettier-ignore-start -->
|
|
323
529
|
```javascript
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
|
328
539
|
```
|
|
540
|
+
<!-- prettier-ignore-end -->
|
|
329
541
|
|
|
330
542
|
---
|
|
331
543
|
|
|
332
544
|
<a name="fail" href="#fail">#</a> <b>fail</b>(): <i>Decoder<empty></i>
|
|
333
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
545
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/fail.js 'Source')
|
|
334
546
|
|
|
335
|
-
|
|
336
|
-
|
|
547
|
+
Rejects all inputs, and always fails with the given error message. May be useful for
|
|
548
|
+
explicitly disallowing keys, or for testing purposes.
|
|
337
549
|
|
|
550
|
+
<!-- prettier-ignore-start -->
|
|
338
551
|
```javascript
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
|
343
563
|
```
|
|
564
|
+
<!-- prettier-ignore-end -->
|
|
344
565
|
|
|
345
566
|
---
|
|
346
567
|
|
|
347
|
-
<a name="mixed" href="#mixed">#</a> <b>mixed</b>: <i>Decoder<mixed></i>
|
|
348
|
-
[<>](https://github.com/nvie/decoders/blob/master/src/constants.js 'Source')<br />
|
|
349
568
|
<a name="unknown" href="#unknown">#</a> <b>unknown</b>: <i>Decoder<unknown></i>
|
|
350
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
569
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')
|
|
570
|
+
<a name="mixed" href="#mixed">#</a> <b>unknown</b>: <i>Decoder<mixed></i>
|
|
571
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/constants.js 'Source')<br />
|
|
351
572
|
|
|
352
|
-
|
|
353
|
-
|
|
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.
|
|
354
576
|
|
|
355
|
-
|
|
577
|
+
(Unknown is called `mixed` in Flow.)
|
|
356
578
|
|
|
357
579
|
```javascript
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
|
363
590
|
```
|
|
364
591
|
|
|
365
592
|
### Compositions
|
|
@@ -372,19 +599,24 @@ decoder for arrays of points: `array(pointDecoder)`, which will be of type
|
|
|
372
599
|
|
|
373
600
|
<a name="optional" href="#optional">#</a>
|
|
374
601
|
<b>optional</b><i><T></i>(<i>Decoder<T></i>): <i>Decoder<T | void></i>
|
|
375
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
602
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
|
|
376
603
|
|
|
377
|
-
|
|
378
|
-
provided that you already have a decoder for <i>T</i>.
|
|
604
|
+
Accepts only the literal value `undefined`, or whatever the given decoder accepts.
|
|
379
605
|
|
|
606
|
+
<!-- prettier-ignore-start -->
|
|
380
607
|
```javascript
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
|
387
618
|
```
|
|
619
|
+
<!-- prettier-ignore-end -->
|
|
388
620
|
|
|
389
621
|
A typical case where `optional` is useful is in decoding objects with optional fields:
|
|
390
622
|
|
|
@@ -410,127 +642,185 @@ Which will decode to type:
|
|
|
410
642
|
|
|
411
643
|
<a name="nullable" href="#nullable">#</a>
|
|
412
644
|
<b>nullable</b><i><T></i>(<i>Decoder<T></i>): <i>Decoder<T | null></i>
|
|
413
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
645
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
|
|
414
646
|
|
|
415
|
-
|
|
416
|
-
provided that you already have a decoder for <i>T</i>.
|
|
647
|
+
Accepts only the literal value `null`, or whatever the given decoder accepts.
|
|
417
648
|
|
|
649
|
+
<!-- prettier-ignore-start -->
|
|
418
650
|
```javascript
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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
|
|
425
661
|
```
|
|
662
|
+
<!-- prettier-ignore-end -->
|
|
426
663
|
|
|
427
664
|
---
|
|
428
665
|
|
|
429
666
|
<a name="maybe" href="#maybe">#</a> <b>maybe</b><i><T></i>(<i>Decoder<T></i>):
|
|
430
667
|
<i>Decoder<?T></i>
|
|
431
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
668
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/optional.js 'Source')
|
|
432
669
|
|
|
433
|
-
|
|
434
|
-
`undefined`**, provided that you already have a decoder for <i>T</i>.
|
|
670
|
+
Accepts only `undefined`, `null`, or whatever the given decoder accepts.
|
|
435
671
|
|
|
672
|
+
<!-- prettier-ignore-start -->
|
|
436
673
|
```javascript
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
|
443
684
|
```
|
|
685
|
+
<!-- prettier-ignore-end -->
|
|
444
686
|
|
|
445
687
|
---
|
|
446
688
|
|
|
447
689
|
<a name="array" href="#array">#</a> <b>array</b><i><T></i>(<i>Decoder<T></i>):
|
|
448
690
|
<i>Decoder<Array<T>></i>
|
|
449
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
691
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/array.js 'Source')
|
|
450
692
|
|
|
451
|
-
|
|
452
|
-
already have a decoder for <i>T</i>.
|
|
693
|
+
Accepts only arrays of whatever the given decoder accepts.
|
|
453
694
|
|
|
695
|
+
<!-- prettier-ignore-start -->
|
|
454
696
|
```javascript
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
697
|
+
const verify = guard(array(string));
|
|
698
|
+
|
|
699
|
+
// 👍
|
|
700
|
+
verify(['hello', 'world']) === ['hello', 'world'];
|
|
701
|
+
|
|
702
|
+
// 👎
|
|
703
|
+
verify(['hello', 1.2]); // throws
|
|
458
704
|
```
|
|
705
|
+
<!-- prettier-ignore-end -->
|
|
459
706
|
|
|
460
707
|
---
|
|
461
708
|
|
|
462
709
|
<a name="nonEmptyArray" href="#nonEmptyArray">#</a>
|
|
463
710
|
<b>nonEmptyArray</b><i><T></i>(<i>Decoder<T></i>):
|
|
464
711
|
<i>Decoder<Array<T>></i>
|
|
465
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
712
|
+
[<>](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<Array<unknown>></i>
|
|
732
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/array.js 'Source')
|
|
466
733
|
|
|
467
|
-
|
|
734
|
+
Accepts any array, but doesn't validate its items further.
|
|
468
735
|
|
|
736
|
+
"poja" means "plain old JavaScript array", a play on ["pojo"](#pojo).
|
|
737
|
+
|
|
738
|
+
<!-- prettier-ignore-start -->
|
|
469
739
|
```javascript
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
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
|
|
474
750
|
```
|
|
751
|
+
<!-- prettier-ignore-end -->
|
|
475
752
|
|
|
476
753
|
---
|
|
477
754
|
|
|
478
755
|
<a name="tuple1" href="#tuple1">#</a>
|
|
479
756
|
<b>tuple1</b><i><T1></i>(<i>Decoder<T1></i>): <i>Decoder<[T1]></i>
|
|
480
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
757
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
|
|
481
758
|
<a name="tuple2" href="#tuple2">#</a> <b>tuple2</b><i><T1,
|
|
482
759
|
T2></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>): <i>Decoder<[T1,
|
|
483
760
|
T2]></i>
|
|
484
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
761
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
|
|
485
762
|
<a name="tuple3" href="#tuple3">#</a> <b>tuple3</b><i><T1, T2,
|
|
486
763
|
T3></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>, <i>Decoder<T3></i>):
|
|
487
764
|
<i>Decoder<[T1, T2, T3]></i>
|
|
488
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
765
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
|
|
489
766
|
<a name="tuple4" href="#tuple4">#</a> <b>tuple4</b><i><T1, T2, T3,
|
|
490
767
|
T4></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>, <i>Decoder<T3></i>,
|
|
491
768
|
<i>Decoder<T4></i>): <i>Decoder<[T1, T2, T3, T4]></i>
|
|
492
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
769
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
|
|
493
770
|
<a name="tuple5" href="#tuple5">#</a> <b>tuple5</b><i><T1, T2, T3, T4,
|
|
494
771
|
T5></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>, <i>Decoder<T3></i>,
|
|
495
772
|
<i>Decoder<T3></i>, <i>Decoder<T4></i>, <i>Decoder<T5></i>):
|
|
496
773
|
<i>Decoder<[T1, T2, T3, T4, T5]></i>
|
|
497
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
774
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')<br />
|
|
498
775
|
<a name="tuple6" href="#tuple6">#</a> <b>tuple6</b><i><T1, T2, T3, T4, T5,
|
|
499
776
|
T6></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>, <i>Decoder<T3></i>,
|
|
500
777
|
<i>Decoder<T4></i>, <i>Decoder<T5></i>, <i>Decoder<T6></i>):
|
|
501
778
|
<i>Decoder<[T1, T2, T3, T4, T5, T6]></i>
|
|
502
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
779
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/tuple.js 'Source')
|
|
503
780
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
number of items in the array is fixed (two) and their types don't have to be homogeneous.
|
|
781
|
+
Accepts a _n_-tuple (an array with exactly _n_ items) of values accepted by the _n_ given
|
|
782
|
+
decoders.
|
|
507
783
|
|
|
784
|
+
<!-- prettier-ignore-start -->
|
|
508
785
|
```javascript
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
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
|
|
512
795
|
```
|
|
796
|
+
<!-- prettier-ignore-end -->
|
|
513
797
|
|
|
514
798
|
---
|
|
515
799
|
|
|
516
800
|
<a name="object" href="#object">#</a> <b>object</b><i><O: { [field: string]:
|
|
517
801
|
Decoder<any> }></i>(mapping: O): <i>Decoder<{ ... }></i>
|
|
518
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
802
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
|
|
519
803
|
|
|
520
|
-
|
|
521
|
-
|
|
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.
|
|
522
806
|
|
|
807
|
+
<!-- prettier-ignore-start -->
|
|
523
808
|
```javascript
|
|
524
|
-
const
|
|
809
|
+
const verify = guard(
|
|
525
810
|
object({
|
|
526
811
|
x: number,
|
|
527
812
|
y: number,
|
|
528
|
-
})
|
|
813
|
+
}),
|
|
529
814
|
);
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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`
|
|
533
822
|
```
|
|
823
|
+
<!-- prettier-ignore-end -->
|
|
534
824
|
|
|
535
825
|
For more information, see also
|
|
536
826
|
[The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
|
|
@@ -539,21 +829,28 @@ For more information, see also
|
|
|
539
829
|
|
|
540
830
|
<a name="exact" href="#exact">#</a> <b>exact</b><i><O: { [field: string]:
|
|
541
831
|
Decoder<any> }></i>(mapping: O): <i>Decoder<{ ... }></i>
|
|
542
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
832
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
|
|
543
833
|
|
|
544
|
-
Like `object()`, but will
|
|
834
|
+
Like `object()`, but will reject inputs that contain extra keys that are not specified
|
|
835
|
+
explicitly.
|
|
545
836
|
|
|
837
|
+
<!-- prettier-ignore-start -->
|
|
546
838
|
```javascript
|
|
547
|
-
const
|
|
839
|
+
const verify = guard(
|
|
548
840
|
exact({
|
|
549
841
|
x: number,
|
|
550
842
|
y: number,
|
|
551
|
-
})
|
|
843
|
+
}),
|
|
552
844
|
);
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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`
|
|
556
852
|
```
|
|
853
|
+
<!-- prettier-ignore-end -->
|
|
557
854
|
|
|
558
855
|
For more information, see also
|
|
559
856
|
[The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
|
|
@@ -562,88 +859,116 @@ For more information, see also
|
|
|
562
859
|
|
|
563
860
|
<a name="inexact" href="#inexact">#</a> <b>inexact</b><i><O: { [field: string]:
|
|
564
861
|
Decoder<any> }></i>(mapping: O): <i>Decoder<{ ... }></i>
|
|
565
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
862
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
|
|
566
863
|
|
|
567
|
-
Like `object()`, but will
|
|
568
|
-
|
|
864
|
+
Like `object()`, but will pass through any extra fields on the input object unvalidated
|
|
865
|
+
that will thus be of `unknown` type statically.
|
|
569
866
|
|
|
867
|
+
<!-- prettier-ignore-start -->
|
|
570
868
|
```javascript
|
|
571
|
-
const
|
|
869
|
+
const verify = guard(
|
|
572
870
|
inexact({
|
|
573
871
|
x: number,
|
|
574
|
-
})
|
|
872
|
+
}),
|
|
575
873
|
);
|
|
576
874
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
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`
|
|
580
881
|
```
|
|
882
|
+
<!-- prettier-ignore-end -->
|
|
581
883
|
|
|
582
884
|
For more information, see also
|
|
583
885
|
[The difference between `object`, `exact`, and `inexact`](#the-difference-between-object-exact-and-inexact).
|
|
584
886
|
|
|
585
887
|
---
|
|
586
888
|
|
|
587
|
-
<a name="
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
[<>](https://github.com/nvie/decoders/blob/master/src/mapping.js 'Source')
|
|
591
|
-
|
|
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>.
|
|
889
|
+
<a name="pojo" href="#pojo">#</a> <b>pojo</b>: <i>Decoder<{ [key: string]: unknown
|
|
890
|
+
}></i>
|
|
891
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/object.js 'Source')
|
|
594
892
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
values are heterogeneous. Whereas with Mappings the keys are typically unknown and the
|
|
598
|
-
values homogeneous.
|
|
893
|
+
Accepts any "plain old JavaScript object", but doesn't validate its keys or values
|
|
894
|
+
further.
|
|
599
895
|
|
|
896
|
+
<!-- prettier-ignore-start -->
|
|
600
897
|
```javascript
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
|
612
909
|
```
|
|
910
|
+
<!-- prettier-ignore-end -->
|
|
613
911
|
|
|
614
912
|
---
|
|
615
913
|
|
|
616
914
|
<a name="dict" href="#dict">#</a> <b>dict</b><i><T></i>(<i>Decoder<T></i>):
|
|
617
915
|
<i>Decoder<{ [string]: <T>}></i>
|
|
618
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
916
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/mapping.js 'Source')
|
|
619
917
|
|
|
620
|
-
|
|
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.
|
|
621
925
|
|
|
622
926
|
```javascript
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
}
|
|
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
|
+
// }
|
|
629
939
|
```
|
|
630
940
|
|
|
631
|
-
|
|
941
|
+
---
|
|
942
|
+
|
|
943
|
+
<a name="mapping" href="#mapping">#</a>
|
|
944
|
+
<b>mapping</b><i><T></i>(<i>Decoder<T></i>): <i>Decoder<Map<string,
|
|
945
|
+
T>></i>
|
|
946
|
+
[<>](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.
|
|
632
949
|
|
|
633
950
|
```javascript
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
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
|
+
// ]);
|
|
639
964
|
```
|
|
640
965
|
|
|
641
966
|
---
|
|
642
967
|
|
|
643
968
|
<a name="json" href="#json">#</a> <b>json</b>: <i>Decoder<JSONValue></i>
|
|
644
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
969
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
|
|
645
970
|
|
|
646
|
-
|
|
971
|
+
Accepts any value that's a valid JSON value:
|
|
647
972
|
|
|
648
973
|
- `null`
|
|
649
974
|
- `string`
|
|
@@ -653,8 +978,10 @@ Returns a decoder capable of decoding **any valid JSON value**:
|
|
|
653
978
|
- `Array<JSONValue>`
|
|
654
979
|
|
|
655
980
|
```javascript
|
|
656
|
-
const
|
|
657
|
-
|
|
981
|
+
const verify = guard(json);
|
|
982
|
+
|
|
983
|
+
// 👍
|
|
984
|
+
verify({
|
|
658
985
|
name: 'Amir',
|
|
659
986
|
age: 27,
|
|
660
987
|
admin: true,
|
|
@@ -669,74 +996,90 @@ Any value returned by `JSON.parse()` should decode without failure.
|
|
|
669
996
|
|
|
670
997
|
<a name="jsonObject" href="#jsonObject">#</a> <b>jsonObject</b>:
|
|
671
998
|
<i>Decoder<JSONObject></i>
|
|
672
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
999
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
|
|
673
1000
|
|
|
674
1001
|
Like `json`, but will only decode when the JSON value is an object.
|
|
675
1002
|
|
|
1003
|
+
<!-- prettier-ignore-start -->
|
|
676
1004
|
```javascript
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
|
|
1005
|
+
const verify = guard(json);
|
|
1006
|
+
|
|
1007
|
+
// 👍
|
|
1008
|
+
verify({}); // ≈ {}
|
|
1009
|
+
verify({ name: 'Amir' }); // ≈ { name: 'Amir' }
|
|
680
1010
|
|
|
681
|
-
//
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1011
|
+
// 👎
|
|
1012
|
+
verify([]); // throws
|
|
1013
|
+
verify([{ name: 'Alice' }]); // throws
|
|
1014
|
+
verify('hello'); // throws
|
|
1015
|
+
verify(null); // throws
|
|
686
1016
|
```
|
|
1017
|
+
<!-- prettier-ignore-end -->
|
|
687
1018
|
|
|
688
1019
|
---
|
|
689
1020
|
|
|
690
1021
|
<a name="jsonArray" href="#jsonArray">#</a> <b>jsonArray</b>:
|
|
691
1022
|
<i>Decoder<JSONArray></i>
|
|
692
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1023
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/json.js 'Source')
|
|
693
1024
|
|
|
694
1025
|
Like `json`, but will only decode when the JSON value is an array.
|
|
695
1026
|
|
|
1027
|
+
<!-- prettier-ignore-start -->
|
|
696
1028
|
```javascript
|
|
697
|
-
const
|
|
698
|
-
mydecoder([]); // OK
|
|
699
|
-
mydecoder([{ name: 'Amir' }]); // OK
|
|
1029
|
+
const verify = guard(json);
|
|
700
1030
|
|
|
701
|
-
//
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
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
|
|
706
1040
|
```
|
|
1041
|
+
<!-- prettier-ignore-end -->
|
|
707
1042
|
|
|
708
1043
|
---
|
|
709
1044
|
|
|
710
1045
|
<a name="either" href="#either">#</a> <b>either</b><i><T1,
|
|
711
1046
|
T2></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>): <i>Decoder<T1 |
|
|
712
1047
|
T2></i><br />
|
|
713
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1048
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
|
|
714
1049
|
<a name="either2" href="#either2">#</a> <b>either2</b><i><T1,
|
|
715
1050
|
T2></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>): <i>Decoder<T1 |
|
|
716
1051
|
T2></i><br />
|
|
717
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1052
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
|
|
718
1053
|
<a name="either3" href="#either3">#</a> <b>either3</b><i><T1, T2,
|
|
719
1054
|
T3></i>(<i>Decoder<T1></i>, <i>Decoder<T2></i>, <i>Decoder<T3></i>):
|
|
720
1055
|
<i>Decoder<T1 | T2 | T3></i>
|
|
721
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1056
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
|
|
1057
|
+
...
|
|
722
1058
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
until 9 (either, either3, either4, ..., either9).
|
|
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`).
|
|
726
1061
|
|
|
1062
|
+
<!-- prettier-ignore-start -->
|
|
727
1063
|
```javascript
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
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
|
|
732
1072
|
```
|
|
1073
|
+
<!-- prettier-ignore-end -->
|
|
733
1074
|
|
|
734
1075
|
---
|
|
735
1076
|
|
|
736
|
-
<a name="
|
|
737
|
-
(Decoder<T> | Decoder<V> | ...) }></i>(field: string,
|
|
738
|
-
<i>Decoder<T | V | ...></i>
|
|
739
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1077
|
+
<a name="disjointUnion" href="#disjointUnion">#</a> <b>disjointUnion</b><i><O: {
|
|
1078
|
+
[field: string]: (Decoder<T> | Decoder<V> | ...) }></i>(field: string,
|
|
1079
|
+
mapping: O): <i>Decoder<T | V | ...></i>
|
|
1080
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/dispatch.js 'Source')
|
|
1081
|
+
|
|
1082
|
+
**NOTE:** In decoders@1.x, this was called `dispatch()`.
|
|
740
1083
|
|
|
741
1084
|
Like the `either` family, but only for building unions of object types with a common field
|
|
742
1085
|
(like a `type` field) that lets you distinguish members.
|
|
@@ -744,19 +1087,19 @@ Like the `either` family, but only for building unions of object types with a co
|
|
|
744
1087
|
The following two decoders are effectively equivalent:
|
|
745
1088
|
|
|
746
1089
|
```javascript
|
|
747
|
-
type Rect = {
|
|
748
|
-
type Circle = {
|
|
749
|
-
//
|
|
750
|
-
//
|
|
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
|
|
751
1094
|
// vvvvvv
|
|
752
|
-
const shape1: Decoder<Rect | Circle> =
|
|
1095
|
+
const shape1: Decoder<Rect | Circle> = disjointUnion('__type', { rect, circle });
|
|
753
1096
|
const shape2: Decoder<Rect | Circle> = either(rect, circle);
|
|
754
1097
|
```
|
|
755
1098
|
|
|
756
|
-
But using `
|
|
757
|
-
reason is that `
|
|
758
|
-
field here, and based on that value, pick which decoder to invoke.
|
|
759
|
-
then also be tailored to the specific decoder.
|
|
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.
|
|
760
1103
|
|
|
761
1104
|
The `either()` version will instead try each decoder in turn until it finds one that
|
|
762
1105
|
matches. If none of the alternatives match, it needs to report all errors, which is
|
|
@@ -766,19 +1109,24 @@ sometimes confusing.
|
|
|
766
1109
|
|
|
767
1110
|
<a name="oneOf" href="#oneOf">#</a> <b>oneOf</b><i><T></i>(<i>Array<T></i>):
|
|
768
1111
|
<i>Decoder<T></i>
|
|
769
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1112
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/either.js 'Source')<br />
|
|
770
1113
|
|
|
771
|
-
|
|
772
|
-
given constants. The returned value will always be one of the given constants at runtime.
|
|
1114
|
+
Accepts any value that is strictly-equal (using `===`) to one of the specified values.
|
|
773
1115
|
|
|
1116
|
+
<!-- prettier-ignore-start -->
|
|
774
1117
|
```javascript
|
|
775
|
-
const
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
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
|
|
781
1128
|
```
|
|
1129
|
+
<!-- prettier-ignore-end -->
|
|
782
1130
|
|
|
783
1131
|
For example, given an array of strings, like so:
|
|
784
1132
|
|
|
@@ -795,72 +1143,109 @@ annotate the type. Either by doing `oneOf([('foo': 'foo'), ('bar': 'bar')])`, or
|
|
|
795
1143
|
|
|
796
1144
|
<a name="instanceOf" href="#instanceOf">#</a>
|
|
797
1145
|
<b>instanceOf</b><i><T></i>(<i>Class<T></i>): <i>Decoder<T></i>
|
|
798
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1146
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/instanceOf.js 'Source')<br />
|
|
799
1147
|
|
|
800
|
-
|
|
1148
|
+
Accepts any value that is an `instanceof` the given class.
|
|
801
1149
|
|
|
802
1150
|
> **NOTE: Help wanted!** The TypeScript annotation for this decoder needs help! If you
|
|
803
1151
|
> know how to express it, please submit a PR. See
|
|
804
|
-
> https://github.com/nvie/decoders/blob/
|
|
1152
|
+
> https://github.com/nvie/decoders/blob/main/src/core/instanceOf.d.ts
|
|
805
1153
|
|
|
1154
|
+
<!-- prettier-ignore-start -->
|
|
806
1155
|
```javascript
|
|
807
|
-
const
|
|
1156
|
+
const verify = guard(instanceOf(Error));
|
|
1157
|
+
|
|
1158
|
+
// 👍
|
|
808
1159
|
const value = new Error('foo');
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1160
|
+
verify(value) === value;
|
|
1161
|
+
|
|
1162
|
+
// 👎
|
|
1163
|
+
verify('foo'); // throws
|
|
1164
|
+
verify(3); // throws
|
|
812
1165
|
```
|
|
1166
|
+
<!-- prettier-ignore-end -->
|
|
813
1167
|
|
|
814
1168
|
---
|
|
815
1169
|
|
|
816
1170
|
<a name="map" href="#map">#</a> <b>map</b><i><T, V></i>(<i>Decoder<T></i>,
|
|
817
1171
|
<i><T></i> => <i><V></i>): <i>Decoder<V></i>
|
|
818
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1172
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/utils.js 'Source')<br />
|
|
819
1173
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
the failure reason.
|
|
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.
|
|
824
1177
|
|
|
1178
|
+
<!-- prettier-ignore-start -->
|
|
825
1179
|
```javascript
|
|
826
1180
|
const upper = map(string, (s) => s.toUpperCase());
|
|
1181
|
+
const verify = guard(upper);
|
|
1182
|
+
|
|
1183
|
+
// 👍
|
|
1184
|
+
verify('foo') === 'FOO';
|
|
827
1185
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
mydecoder('foo') === 'FOO';
|
|
1186
|
+
// 👎
|
|
1187
|
+
verify(4); // throws
|
|
831
1188
|
```
|
|
1189
|
+
<!-- prettier-ignore-end -->
|
|
832
1190
|
|
|
833
1191
|
---
|
|
834
1192
|
|
|
835
1193
|
<a name="compose" href="#compose">#</a> <b>compose</b><i><T,
|
|
836
1194
|
V></i>(<i>Decoder<T></i>, <i>Decoder<V, T></i>): <i>Decoder<V></i>
|
|
837
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1195
|
+
[<>](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><T></i>(<i>Decoder<T></i>, <i><T> => boolean</i>,
|
|
1209
|
+
string): <i>Decoder<T></i>
|
|
1210
|
+
[<>](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.
|
|
838
1213
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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 -->
|
|
843
1231
|
|
|
844
|
-
|
|
845
|
-
|
|
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.
|
|
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.
|
|
848
1234
|
|
|
849
1235
|
---
|
|
850
1236
|
|
|
851
1237
|
<a name="describe" href="#describe">#</a>
|
|
852
1238
|
<b>describe</b><i><T></i>(<i>Decoder<T></i>, <i>string</i>):
|
|
853
1239
|
<i>Decoder<T></i>
|
|
854
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1240
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/describe.js 'Source')<br />
|
|
855
1241
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
low-level/technical errors.
|
|
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.
|
|
859
1244
|
|
|
860
1245
|
```javascript
|
|
861
1246
|
const vowel = describe(
|
|
862
1247
|
either5(constant('a'), constant('e'), constant('i'), constant('o'), constant('u')),
|
|
863
|
-
'Must be vowel'
|
|
1248
|
+
'Must be vowel',
|
|
864
1249
|
);
|
|
865
1250
|
```
|
|
866
1251
|
|
|
@@ -868,7 +1253,7 @@ const vowel = describe(
|
|
|
868
1253
|
|
|
869
1254
|
<a name="lazy" href="#lazy">#</a> <b>lazy</b><i><T></i>(() =>
|
|
870
1255
|
<i>Decoder<T></i>): <i>Decoder<T></i>
|
|
871
|
-
[<>](https://github.com/nvie/decoders/blob/
|
|
1256
|
+
[<>](https://github.com/nvie/decoders/blob/main/src/core/lazy.js 'Source')<br />
|
|
872
1257
|
|
|
873
1258
|
Lazily evaluate the given decoder. This is useful to build self-referential types for
|
|
874
1259
|
recursive data structures. Example:
|
|
@@ -916,11 +1301,11 @@ And a runtime input of:
|
|
|
916
1301
|
}
|
|
917
1302
|
```
|
|
918
1303
|
|
|
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
|
|
923
|
-
| `inexact(thing)` | retained | `{a: "hi", b: 42, c: "extra"}` | `{a: string, b: number, [string]:
|
|
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}` |
|
|
924
1309
|
|
|
925
1310
|
### Building custom decoders
|
|
926
1311
|
|
|
@@ -944,7 +1329,7 @@ const numericString: Decoder<number> = map(
|
|
|
944
1329
|
// At runtime, expect to read a string...
|
|
945
1330
|
string,
|
|
946
1331
|
// ...but return it as a number
|
|
947
|
-
(s) => Number(s)
|
|
1332
|
+
(s) => Number(s),
|
|
948
1333
|
);
|
|
949
1334
|
```
|
|
950
1335
|
|
|
@@ -962,15 +1347,15 @@ business logic outside decoders makes them more reusable and composable.
|
|
|
962
1347
|
#### Adding predicates
|
|
963
1348
|
|
|
964
1349
|
The easiest way to decode using an existing decoder, but enforcing extra runtime checks on
|
|
965
|
-
their values is by
|
|
1350
|
+
their values is by wrapping it in a `predicate(...)` construction:
|
|
966
1351
|
|
|
967
1352
|
```js
|
|
968
|
-
const odd =
|
|
969
|
-
|
|
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
|
-
);
|
|
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');
|
|
976
1355
|
```
|
|
1356
|
+
|
|
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
|