1 | <p align="center">
|
2 | <img src="media/logo.png" width="300">
|
3 | <br>
|
4 | <br>
|
5 | </p>
|
6 |
|
7 | [](https://codecov.io/gh/sindresorhus/ow)
|
8 | [](https://bundlephobia.com/result?p=ow)
|
9 | [](https://packagephobia.now.sh/result?p=ow)
|
10 |
|
11 | > Function argument validation for humans
|
12 |
|
13 | For schema validation, I recommend [`zod`](https://github.com/colinhacks/zod).
|
14 |
|
15 | ## Highlights
|
16 |
|
17 | - Expressive chainable API
|
18 | - Lots of built-in validations
|
19 | - Supports custom validations
|
20 | - Automatic label inference in Node.js
|
21 | - Written in TypeScript
|
22 |
|
23 | ## Install
|
24 |
|
25 | ```sh
|
26 | npm install ow
|
27 | ```
|
28 |
|
29 | ## Usage
|
30 |
|
31 | ```ts
|
32 | import ow from 'ow';
|
33 |
|
34 | const unicorn = input => {
|
35 | ow(input, ow.string.minLength(5));
|
36 |
|
37 | // …
|
38 | };
|
39 |
|
40 | unicorn(3);
|
41 | //=> ArgumentError: Expected `input` to be of type `string` but received type `number`
|
42 |
|
43 | unicorn('yo');
|
44 | //=> ArgumentError: Expected string `input` to have a minimum length of `5`, got `yo`
|
45 | ```
|
46 |
|
47 | We can also match the shape of an object.
|
48 |
|
49 | ```ts
|
50 | import ow from 'ow';
|
51 |
|
52 | const unicorn = {
|
53 | rainbow: '🌈',
|
54 | stars: {
|
55 | value: '🌟'
|
56 | }
|
57 | };
|
58 |
|
59 | ow(unicorn, ow.object.exactShape({
|
60 | rainbow: ow.string,
|
61 | stars: {
|
62 | value: ow.number
|
63 | }
|
64 | }));
|
65 | //=> ArgumentError: Expected property `stars.value` to be of type `number` but received type `string` in object `unicorn`
|
66 | ```
|
67 |
|
68 | ***Note:*** If you intend on using `ow` for development purposes only, use `import ow from 'ow/dev-only'` instead of the usual `import ow from '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.
|
69 |
|
70 | ## API
|
71 |
|
72 | [Complete API documentation](https://sindresorhus.com/ow/)
|
73 |
|
74 | Ow includes TypeScript type guards, so using it will narrow the type of previously-unknown values.
|
75 |
|
76 | ```ts
|
77 | function (input: unknown) {
|
78 | input.slice(0, 3) // Error, Property 'slice' does not exist on type 'unknown'
|
79 |
|
80 | ow(input, ow.string)
|
81 |
|
82 | input.slice(0, 3) // OK
|
83 | }
|
84 | ```
|
85 |
|
86 | ### ow(value, predicate)
|
87 |
|
88 | Test if `value` matches the provided `predicate`. Throws an `ArgumentError` if the test fails.
|
89 |
|
90 | ### ow(value, label, predicate)
|
91 |
|
92 | Test if `value` matches the provided `predicate`. Throws an `ArgumentError` with the specified `label` if the test fails.
|
93 |
|
94 | 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.
|
95 |
|
96 | ### ow.isValid(value, predicate)
|
97 |
|
98 | Returns `true` if the value matches the predicate, otherwise returns `false`.
|
99 |
|
100 | ### ow.create(predicate)
|
101 |
|
102 | Create a reusable validator.
|
103 |
|
104 | ```ts
|
105 | const checkPassword = ow.create(ow.string.minLength(6));
|
106 |
|
107 | const password = 'foo';
|
108 |
|
109 | checkPassword(password);
|
110 | //=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
|
111 | ```
|
112 |
|
113 | ### ow.create(label, predicate)
|
114 |
|
115 | Create a reusable validator with a specific `label`.
|
116 |
|
117 | ```ts
|
118 | const checkPassword = ow.create('password', ow.string.minLength(6));
|
119 |
|
120 | checkPassword('foo');
|
121 | //=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
|
122 | ```
|
123 |
|
124 | ### ow.any(...predicate[])
|
125 |
|
126 | Returns a predicate that verifies if the value matches at least one of the given predicates.
|
127 |
|
128 | ```ts
|
129 | ow('foo', ow.any(ow.string.maxLength(3), ow.number));
|
130 | ```
|
131 |
|
132 | ### ow.optional.{type}
|
133 |
|
134 | Makes the predicate optional. An optional predicate means that it doesn't fail if the value is `undefined`.
|
135 |
|
136 | ```ts
|
137 | ow(1, ow.optional.number);
|
138 |
|
139 | ow(undefined, ow.optional.number);
|
140 | ```
|
141 |
|
142 | ### ow.{type}
|
143 |
|
144 | 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.
|
145 |
|
146 | [Predicate docs.](https://sindresorhus.com/ow/types/Predicates.html)
|
147 |
|
148 | #### Primitives
|
149 |
|
150 | - `undefined`
|
151 | - `null`
|
152 | - `string`
|
153 | - `number`
|
154 | - `boolean`
|
155 | - `symbol`
|
156 |
|
157 | #### Built-in types
|
158 |
|
159 | - `array`
|
160 | - `function`
|
161 | - `buffer`
|
162 | - `object`
|
163 | - `regExp`
|
164 | - `date`
|
165 | - `error`
|
166 | - `promise`
|
167 | - `map`
|
168 | - `set`
|
169 | - `weakMap`
|
170 | - `weakSet`
|
171 |
|
172 | #### Typed arrays
|
173 |
|
174 | - `int8Array`
|
175 | - `uint8Array`
|
176 | - `uint8ClampedArray`
|
177 | - `int16Array`
|
178 | - `uint16Array`
|
179 | - `int32Array`
|
180 | - `uint32Array`
|
181 | - `float32Array`
|
182 | - `float64Array`
|
183 |
|
184 | #### Structured data
|
185 |
|
186 | - `arrayBuffer`
|
187 | - `dataView`
|
188 | - `sharedArrayBuffer`
|
189 |
|
190 | #### Miscellaneous
|
191 |
|
192 | - `nan`
|
193 | - `nullOrUndefined`
|
194 | - `iterable`
|
195 | - `typedArray`
|
196 |
|
197 | ### Predicates
|
198 |
|
199 | The following predicates are available on every type.
|
200 |
|
201 | #### not
|
202 |
|
203 | Inverts the following predicate.
|
204 |
|
205 | ```ts
|
206 | ow(1, ow.number.not.infinite);
|
207 |
|
208 | ow('', ow.string.not.empty);
|
209 | //=> ArgumentError: Expected string to not be empty, got ``
|
210 | ```
|
211 |
|
212 | #### is(fn)
|
213 |
|
214 | Use a custom validation function. Return `true` if the value matches the validation, return `false` if it doesn't.
|
215 |
|
216 | ```ts
|
217 | ow(1, ow.number.is(x => x < 10));
|
218 |
|
219 | ow(1, ow.number.is(x => x > 10));
|
220 | //=> ArgumentError: Expected `1` to pass custom validation function
|
221 | ```
|
222 |
|
223 | Instead of returning `false`, you can also return a custom error message which results in a failure.
|
224 |
|
225 | ```ts
|
226 | const greaterThan = (max: number, x: number) => {
|
227 | return x > max || `Expected \`${x}\` to be greater than \`${max}\``;
|
228 | };
|
229 |
|
230 | ow(5, ow.number.is(x => greaterThan(10, x)));
|
231 | //=> ArgumentError: Expected `5` to be greater than `10`
|
232 | ```
|
233 |
|
234 | #### validate(fn)
|
235 |
|
236 | Use a custom validation object. The difference with `is` is that the function should return a validation object, which allows more flexibility.
|
237 |
|
238 | ```ts
|
239 | ow(1, ow.number.validate(value => ({
|
240 | validator: value > 10,
|
241 | message: `Expected value to be greater than 10, got ${value}`
|
242 | })));
|
243 | //=> ArgumentError: (number) Expected value to be greater than 10, got 1
|
244 | ```
|
245 |
|
246 | You can also pass in a function as `message` value which accepts the label as argument.
|
247 |
|
248 | ```ts
|
249 | ow(1, 'input', ow.number.validate(value => ({
|
250 | validator: value > 10,
|
251 | message: label => `Expected ${label} to be greater than 10, got ${value}`
|
252 | })));
|
253 | //=> ArgumentError: Expected number `input` to be greater than 10, got 1
|
254 | ```
|
255 |
|
256 | #### message(string | fn)
|
257 |
|
258 | Provide a custom message:
|
259 |
|
260 | ```ts
|
261 | ow('🌈', 'unicorn', ow.string.equals('🦄').message('Expected unicorn, got rainbow'));
|
262 | //=> ArgumentError: Expected unicorn, got rainbow
|
263 | ```
|
264 |
|
265 | You can also pass in a function which receives the value as the first parameter and the label as the second parameter and is expected to return the message.
|
266 |
|
267 | ```ts
|
268 | ow('🌈', ow.string.minLength(5).message((value, label) => `Expected ${label}, to have a minimum length of 5, got \`${value}\``));
|
269 | //=> ArgumentError: Expected string, to be have a minimum length of 5, got `🌈`
|
270 | ```
|
271 |
|
272 | It's also possible to add a separate message per validation:
|
273 |
|
274 | ```ts
|
275 | ow(
|
276 | '1234',
|
277 | ow.string
|
278 | .minLength(5).message((value, label) => `Expected ${label}, to be have a minimum length of 5, got \`${value}\``)
|
279 | .url.message('This is no url')
|
280 | );
|
281 | //=> ArgumentError: Expected string, to be have a minimum length of 5, got `1234`
|
282 |
|
283 | ow(
|
284 | '12345',
|
285 | ow.string
|
286 | .minLength(5).message((value, label) => `Expected ${label}, to be have a minimum length of 5, got \`${value}\``)
|
287 | .url.message('This is no url')
|
288 | );
|
289 | //=> ArgumentError: This is no url
|
290 | ```
|
291 |
|
292 | This can be useful for creating your own reusable validators which can be extracted to a separate npm package.
|
293 |
|
294 | ### TypeScript
|
295 |
|
296 | **Requires TypeScript 4.7 or later.**
|
297 |
|
298 | Ow includes a type utility that lets you to extract a TypeScript type from the given predicate.
|
299 |
|
300 | ```ts
|
301 | import ow, {Infer} from 'ow';
|
302 |
|
303 | const userPredicate = ow.object.exactShape({
|
304 | name: ow.string
|
305 | });
|
306 |
|
307 | type User = Infer<typeof userPredicate>;
|
308 | ```
|
309 |
|
310 | ## Related
|
311 |
|
312 | - [@sindresorhus/is](https://github.com/sindresorhus/is) - Type check values
|
313 | - [ngx-ow](https://github.com/SamVerschueren/ngx-ow) - Angular form validation on steroids
|