1 | <p align="center">
|
2 | <img src="media/logo.png" width="300">
|
3 | <br>
|
4 | <br>
|
5 | </p>
|
6 |
|
7 | [![Build Status](https://travis-ci.org/sindresorhus/ow.svg?branch=master)](https://travis-ci.org/sindresorhus/ow) [![Coverage Status](https://codecov.io/gh/sindresorhus/ow/branch/master/graph/badge.svg)](https://codecov.io/gh/sindresorhus/ow) [![gzip size](https://badgen.net/bundlephobia/minzip/ow)](https://bundlephobia.com/result?p=ow) [![install size](https://packagephobia.now.sh/badge?p=ow)](https://packagephobia.now.sh/result?p=ow)
|
8 |
|
9 | > Function argument validation for humans
|
10 |
|
11 | ## Highlights
|
12 |
|
13 | - Expressive chainable API
|
14 | - Lots of built-in validations
|
15 | - Supports custom validations
|
16 | - Automatic label inference in Node.js
|
17 | - Written in TypeScript
|
18 |
|
19 | ## Install
|
20 |
|
21 | ```
|
22 | $ npm install ow
|
23 | ```
|
24 |
|
25 | ## Usage
|
26 |
|
27 | ```ts
|
28 | import ow from 'ow';
|
29 |
|
30 | const unicorn = input => {
|
31 | ow(input, ow.string.minLength(5));
|
32 |
|
33 | // …
|
34 | };
|
35 |
|
36 | unicorn(3);
|
37 | //=> ArgumentError: Expected `input` to be of type `string` but received type `number`
|
38 |
|
39 | unicorn('yo');
|
40 | //=> ArgumentError: Expected string `input` to have a minimum length of `5`, got `yo`
|
41 | ```
|
42 |
|
43 | We can also match the shape of an object.
|
44 |
|
45 | ```ts
|
46 | import ow from 'ow';
|
47 |
|
48 | const unicorn = {
|
49 | rainbow: '🌈',
|
50 | stars: {
|
51 | value: '🌟'
|
52 | }
|
53 | };
|
54 |
|
55 | ow(unicorn, ow.object.exactShape({
|
56 | rainbow: ow.string,
|
57 | stars: {
|
58 | value: ow.number
|
59 | }
|
60 | }));
|
61 | //=> ArgumentError: Expected property `stars.value` to be of type `number` but received type `string` in object `unicorn`
|
62 | ```
|
63 |
|
64 | ***Note:*** If you intend on using `ow` for development purposes only, use `require('ow/dev-only')` instead of the usual `import 'ow'`, and run the bundler with `NODE_ENV` set to `production` (e.g. `$ NODE_ENV="production" parcel build index.js`). This will make `ow` automatically export a shim when running in production, which should result in a significantly lower bundle size.
|
65 |
|
66 | ## API
|
67 |
|
68 | [Complete API documentation](https://sindresorhus.com/ow)
|
69 |
|
70 | ### ow(value, predicate)
|
71 |
|
72 | Test if `value` matches the provided `predicate`. Throws an `ArgumentError` if the test fails.
|
73 |
|
74 | ### ow(value, label, predicate)
|
75 |
|
76 | Test if `value` matches the provided `predicate`. Throws an `ArgumentError` with the specified `label` if the test fails.
|
77 |
|
78 | The `label` is automatically inferred in Node.js but you can override it by passing in a value for `label`. The automatic label inference doesn't work in the browser.
|
79 |
|
80 | ### ow.isValid(value, predicate)
|
81 |
|
82 | Returns `true` if the value matches the predicate, otherwise returns `false`.
|
83 |
|
84 | ### ow.create(predicate)
|
85 |
|
86 | Create a reusable validator.
|
87 |
|
88 | ```ts
|
89 | const checkPassword = ow.create(ow.string.minLength(6));
|
90 |
|
91 | const password = 'foo';
|
92 |
|
93 | checkPassword(password);
|
94 | //=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
|
95 | ```
|
96 |
|
97 | ### ow.create(label, predicate)
|
98 |
|
99 | Create a reusable validator with a specific `label`.
|
100 |
|
101 | ```ts
|
102 | const checkPassword = ow.create('password', ow.string.minLength(6));
|
103 |
|
104 | checkPassword('foo');
|
105 | //=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
|
106 | ```
|
107 |
|
108 | ### ow.any(...predicate[])
|
109 |
|
110 | Returns a predicate that verifies if the value matches at least one of the given predicates.
|
111 |
|
112 | ```ts
|
113 | ow('foo', ow.any(ow.string.maxLength(3), ow.number));
|
114 | ```
|
115 |
|
116 | ### ow.optional.{type}
|
117 |
|
118 | Makes the predicate optional. An optional predicate means that it doesn't fail if the value is `undefined`.
|
119 |
|
120 | ```ts
|
121 | ow(1, ow.optional.number);
|
122 |
|
123 | ow(undefined, ow.optional.number);
|
124 | ```
|
125 |
|
126 | ### ow.{type}
|
127 |
|
128 | All the below types return a predicate. Every predicate has some extra operators that you can use to test the value even more fine-grained.
|
129 |
|
130 | #### Primitives
|
131 |
|
132 | - [`undefined`](https://sindresorhus.com/ow/interfaces/ow.html#undefined)
|
133 | - [`null`](https://sindresorhus.com/ow/interfaces/ow.html#null)
|
134 | - [`string`](https://sindresorhus.com/ow/classes/stringpredicate.html)
|
135 | - [`number`](https://sindresorhus.com/ow/classes/numberpredicate.html)
|
136 | - [`boolean`](https://sindresorhus.com/ow/classes/booleanpredicate.html)
|
137 | - [`symbol`](https://sindresorhus.com/ow/interfaces/ow.html#symbol)
|
138 |
|
139 | #### Built-in types
|
140 |
|
141 | - [`array`](https://sindresorhus.com/ow/classes/arraypredicate.html)
|
142 | - [`function`](https://sindresorhus.com/ow/interfaces/ow.html#function)
|
143 | - [`buffer`](https://sindresorhus.com/ow/interfaces/ow.html#buffer)
|
144 | - [`object`](https://sindresorhus.com/ow/classes/objectpredicate.html)
|
145 | - [`regExp`](https://sindresorhus.com/ow/interfaces/ow.html#regexp)
|
146 | - [`date`](https://sindresorhus.com/ow/classes/datepredicate.html)
|
147 | - [`error`](https://sindresorhus.com/ow/classes/errorpredicate.html)
|
148 | - [`promise`](https://sindresorhus.com/ow/interfaces/ow.html#promise)
|
149 | - [`map`](https://sindresorhus.com/ow/classes/mappredicate.html)
|
150 | - [`set`](https://sindresorhus.com/ow/classes/setpredicate.html)
|
151 | - [`weakMap`](https://sindresorhus.com/ow/classes/weakmappredicate.html)
|
152 | - [`weakSet`](https://sindresorhus.com/ow/classes/weaksetpredicate.html)
|
153 |
|
154 | #### Typed arrays
|
155 |
|
156 | - [`int8Array`](https://sindresorhus.com/ow/interfaces/ow.html#int8Array)
|
157 | - [`uint8Array`](https://sindresorhus.com/ow/interfaces/ow.html#uint8Array)
|
158 | - [`uint8ClampedArray`](https://sindresorhus.com/ow/interfaces/ow.html#uint8ClampedArray)
|
159 | - [`int16Array`](https://sindresorhus.com/ow/interfaces/ow.html#int16Array)
|
160 | - [`uint16Array`](https://sindresorhus.com/ow/interfaces/ow.html#uint16Array)
|
161 | - [`int32Array`](https://sindresorhus.com/ow/interfaces/ow.html#in32Array)
|
162 | - [`uint32Array`](https://sindresorhus.com/ow/interfaces/ow.html#uin32Array)
|
163 | - [`float32Array`](https://sindresorhus.com/ow/interfaces/ow.html#float32Array)
|
164 | - [`float64Array`](https://sindresorhus.com/ow/interfaces/ow.html#float64Array)
|
165 |
|
166 | #### Structured data
|
167 |
|
168 | - [`arrayBuffer`](https://sindresorhus.com/ow/interfaces/ow.html#arraybuffer)
|
169 | - [`dataView`](https://sindresorhus.com/ow/interfaces/ow.html#dataview)
|
170 |
|
171 | #### Miscellaneous
|
172 |
|
173 | - [`nan`](https://sindresorhus.com/ow/interfaces/ow.html#nan)
|
174 | - [`nullOrUndefined`](https://sindresorhus.com/ow/interfaces/ow.html#nullorundefined)
|
175 | - [`iterable`](https://sindresorhus.com/ow/interfaces/ow.html#iterable)
|
176 | - [`typedArray`](https://sindresorhus.com/ow/interfaces/ow.html#typedarray)
|
177 |
|
178 | ### Predicates
|
179 |
|
180 | The following predicates are available on every type.
|
181 |
|
182 | #### not
|
183 |
|
184 | Inverts the following predicate.
|
185 |
|
186 | ```ts
|
187 | ow(1, ow.number.not.infinite);
|
188 |
|
189 | ow('', ow.string.not.empty);
|
190 | //=> ArgumentError: Expected string to not be empty, got ``
|
191 | ```
|
192 |
|
193 | #### is(fn)
|
194 |
|
195 | Use a custom validation function. Return `true` if the value matches the validation, return `false` if it doesn't.
|
196 |
|
197 | ```ts
|
198 | ow(1, ow.number.is(x => x < 10));
|
199 |
|
200 | ow(1, ow.number.is(x => x > 10));
|
201 | //=> ArgumentError: Expected `1` to pass custom validation function
|
202 | ```
|
203 |
|
204 | Instead of returning `false`, you can also return a custom error message which results in a failure.
|
205 |
|
206 | ```ts
|
207 | const greaterThan = (max: number, x: number) => {
|
208 | return x > max || `Expected \`${x}\` to be greater than \`${max}\``;
|
209 | };
|
210 |
|
211 | ow(5, ow.number.is(x => greaterThan(10, x)));
|
212 | //=> ArgumentError: Expected `5` to be greater than `10`
|
213 | ```
|
214 |
|
215 | #### validate(fn)
|
216 |
|
217 | Use a custom validation object. The difference with `is` is that the function should return a validation object, which allows more flexibility.
|
218 |
|
219 | ```ts
|
220 | ow(1, ow.number.validate(value => ({
|
221 | validator: value > 10,
|
222 | message: `Expected value to be greater than 10, got ${value}`
|
223 | })));
|
224 | //=> ArgumentError: (number) Expected value to be greater than 10, got 1
|
225 | ```
|
226 |
|
227 | You can also pass in a function as `message` value which accepts the label as argument.
|
228 |
|
229 | ```ts
|
230 | ow(1, 'input', ow.number.validate(value => ({
|
231 | validator: value > 10,
|
232 | message: label => `Expected ${label} to be greater than 10, got ${value}`
|
233 | })));
|
234 | //=> ArgumentError: Expected number `input` to be greater than 10, got 1
|
235 | ```
|
236 |
|
237 | This can be useful for creating your own reusable validators which can be extracted to a separate npm package.
|
238 |
|
239 | ## Maintainers
|
240 |
|
241 | - [Sindre Sorhus](https://github.com/sindresorhus)
|
242 | - [Sam Verschueren](https://github.com/SamVerschueren)
|
243 |
|
244 | ## Related
|
245 |
|
246 | - [@sindresorhus/is](https://github.com/sindresorhus/is) - Type check values
|
247 | - [ngx-ow](https://github.com/SamVerschueren/ngx-ow) - Angular form validation on steroids
|
248 |
|