UNPKG

9.43 kBMarkdownView Raw
1<p align="center">
2 <img src="media/logo.png" width="300">
3 <br>
4 <br>
5</p>
6
7[![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*If you use CommonJS, you need to import is as `const {default: ow} = require('ow')`.*
28
29```ts
30import ow from 'ow';
31
32const unicorn = input => {
33 ow(input, ow.string.minLength(5));
34
35 // …
36};
37
38unicorn(3);
39//=> ArgumentError: Expected `input` to be of type `string` but received type `number`
40
41unicorn('yo');
42//=> ArgumentError: Expected string `input` to have a minimum length of `5`, got `yo`
43```
44
45We can also match the shape of an object.
46
47```ts
48import ow from 'ow';
49
50const unicorn = {
51 rainbow: '🌈',
52 stars: {
53 value: '🌟'
54 }
55};
56
57ow(unicorn, ow.object.exactShape({
58 rainbow: ow.string,
59 stars: {
60 value: ow.number
61 }
62}));
63//=> ArgumentError: Expected property `stars.value` to be of type `number` but received type `string` in object `unicorn`
64```
65
66***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.
67
68## API
69
70[Complete API documentation](https://sindresorhus.com/ow/interfaces/ow.html)
71
72Ow includes TypeScript type guards, so using it will narrow the type of previously-unknown values.
73
74```ts
75function (input: unknown) {
76 input.slice(0, 3) // Error, Property 'slice' does not exist on type 'unknown'
77
78 ow(input, ow.string)
79
80 input.slice(0, 3) // OK
81}
82```
83
84### ow(value, predicate)
85
86Test if `value` matches the provided `predicate`. Throws an `ArgumentError` if the test fails.
87
88### ow(value, label, predicate)
89
90Test if `value` matches the provided `predicate`. Throws an `ArgumentError` with the specified `label` if the test fails.
91
92The `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.
93
94### ow.isValid(value, predicate)
95
96Returns `true` if the value matches the predicate, otherwise returns `false`.
97
98### ow.create(predicate)
99
100Create a reusable validator.
101
102```ts
103const checkPassword = ow.create(ow.string.minLength(6));
104
105const password = 'foo';
106
107checkPassword(password);
108//=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
109```
110
111### ow.create(label, predicate)
112
113Create a reusable validator with a specific `label`.
114
115```ts
116const checkPassword = ow.create('password', ow.string.minLength(6));
117
118checkPassword('foo');
119//=> ArgumentError: Expected string `password` to have a minimum length of `6`, got `foo`
120```
121
122### ow.any(...predicate[])
123
124Returns a predicate that verifies if the value matches at least one of the given predicates.
125
126```ts
127ow('foo', ow.any(ow.string.maxLength(3), ow.number));
128```
129
130### ow.optional.{type}
131
132Makes the predicate optional. An optional predicate means that it doesn't fail if the value is `undefined`.
133
134```ts
135ow(1, ow.optional.number);
136
137ow(undefined, ow.optional.number);
138```
139
140### ow.{type}
141
142All the below types return a predicate. Every predicate has some extra operators that you can use to test the value even more fine-grained.
143
144#### Primitives
145
146- [`undefined`](https://sindresorhus.com/ow/interfaces/ow.html#undefined)
147- [`null`](https://sindresorhus.com/ow/interfaces/ow.html#null)
148- [`string`](https://sindresorhus.com/ow/classes/stringpredicate.html)
149- [`number`](https://sindresorhus.com/ow/classes/numberpredicate.html)
150- [`boolean`](https://sindresorhus.com/ow/classes/booleanpredicate.html)
151- [`symbol`](https://sindresorhus.com/ow/interfaces/ow.html#symbol)
152
153#### Built-in types
154
155- [`array`](https://sindresorhus.com/ow/classes/arraypredicate.html)
156- [`function`](https://sindresorhus.com/ow/interfaces/ow.html#function)
157- [`buffer`](https://sindresorhus.com/ow/interfaces/ow.html#buffer)
158- [`object`](https://sindresorhus.com/ow/classes/objectpredicate.html)
159- [`regExp`](https://sindresorhus.com/ow/interfaces/ow.html#regexp)
160- [`date`](https://sindresorhus.com/ow/classes/datepredicate.html)
161- [`error`](https://sindresorhus.com/ow/classes/errorpredicate.html)
162- [`promise`](https://sindresorhus.com/ow/interfaces/ow.html#promise)
163- [`map`](https://sindresorhus.com/ow/classes/mappredicate.html)
164- [`set`](https://sindresorhus.com/ow/classes/setpredicate.html)
165- [`weakMap`](https://sindresorhus.com/ow/classes/weakmappredicate.html)
166- [`weakSet`](https://sindresorhus.com/ow/classes/weaksetpredicate.html)
167
168#### Typed arrays
169
170- [`int8Array`](https://sindresorhus.com/ow/interfaces/ow.html#int8Array)
171- [`uint8Array`](https://sindresorhus.com/ow/interfaces/ow.html#uint8Array)
172- [`uint8ClampedArray`](https://sindresorhus.com/ow/interfaces/ow.html#uint8ClampedArray)
173- [`int16Array`](https://sindresorhus.com/ow/interfaces/ow.html#int16Array)
174- [`uint16Array`](https://sindresorhus.com/ow/interfaces/ow.html#uint16Array)
175- [`int32Array`](https://sindresorhus.com/ow/interfaces/ow.html#in32Array)
176- [`uint32Array`](https://sindresorhus.com/ow/interfaces/ow.html#uin32Array)
177- [`float32Array`](https://sindresorhus.com/ow/interfaces/ow.html#float32Array)
178- [`float64Array`](https://sindresorhus.com/ow/interfaces/ow.html#float64Array)
179
180#### Structured data
181
182- [`arrayBuffer`](https://sindresorhus.com/ow/interfaces/ow.html#arraybuffer)
183- [`dataView`](https://sindresorhus.com/ow/interfaces/ow.html#dataview)
184
185#### Miscellaneous
186
187- [`nan`](https://sindresorhus.com/ow/interfaces/ow.html#nan)
188- [`nullOrUndefined`](https://sindresorhus.com/ow/interfaces/ow.html#nullorundefined)
189- [`iterable`](https://sindresorhus.com/ow/interfaces/ow.html#iterable)
190- [`typedArray`](https://sindresorhus.com/ow/interfaces/ow.html#typedarray)
191
192### Predicates
193
194The following predicates are available on every type.
195
196#### not
197
198Inverts the following predicate.
199
200```ts
201ow(1, ow.number.not.infinite);
202
203ow('', ow.string.not.empty);
204//=> ArgumentError: Expected string to not be empty, got ``
205```
206
207#### is(fn)
208
209Use a custom validation function. Return `true` if the value matches the validation, return `false` if it doesn't.
210
211```ts
212ow(1, ow.number.is(x => x < 10));
213
214ow(1, ow.number.is(x => x > 10));
215//=> ArgumentError: Expected `1` to pass custom validation function
216```
217
218Instead of returning `false`, you can also return a custom error message which results in a failure.
219
220```ts
221const greaterThan = (max: number, x: number) => {
222 return x > max || `Expected \`${x}\` to be greater than \`${max}\``;
223};
224
225ow(5, ow.number.is(x => greaterThan(10, x)));
226//=> ArgumentError: Expected `5` to be greater than `10`
227```
228
229#### validate(fn)
230
231Use a custom validation object. The difference with `is` is that the function should return a validation object, which allows more flexibility.
232
233```ts
234ow(1, ow.number.validate(value => ({
235 validator: value > 10,
236 message: `Expected value to be greater than 10, got ${value}`
237})));
238//=> ArgumentError: (number) Expected value to be greater than 10, got 1
239```
240
241You can also pass in a function as `message` value which accepts the label as argument.
242
243```ts
244ow(1, 'input', ow.number.validate(value => ({
245 validator: value > 10,
246 message: label => `Expected ${label} to be greater than 10, got ${value}`
247})));
248//=> ArgumentError: Expected number `input` to be greater than 10, got 1
249```
250
251#### message(string | fn)
252
253Provide a custom message:
254
255```ts
256ow('🌈', 'unicorn', ow.string.equals('🦄').message('Expected unicorn, got rainbow'));
257//=> ArgumentError: Expected unicorn, got rainbow
258```
259
260You 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.
261
262```ts
263ow('🌈', ow.string.minLength(5).message((value, label) => `Expected ${label}, to have a minimum length of 5, got \`${value}\``));
264//=> ArgumentError: Expected string, to be have a minimum length of 5, got `🌈`
265```
266
267It's also possible to add a separate message per validation:
268
269```ts
270ow(
271 '1234',
272 ow.string
273 .minLength(5).message((value, label) => `Expected ${label}, to be have a minimum length of 5, got \`${value}\``)
274 .url.message('This is no url')
275);
276//=> ArgumentError: Expected string, to be have a minimum length of 5, got `1234`
277
278ow(
279 '12345',
280 ow.string
281 .minLength(5).message((value, label) => `Expected ${label}, to be have a minimum length of 5, got \`${value}\``)
282 .url.message('This is no url')
283);
284//=> ArgumentError: This is no url
285```
286
287This can be useful for creating your own reusable validators which can be extracted to a separate npm package.
288
289## Maintainers
290
291- [Sindre Sorhus](https://github.com/sindresorhus)
292- [Sam Verschueren](https://github.com/SamVerschueren)
293
294## Related
295
296- [@sindresorhus/is](https://github.com/sindresorhus/is) - Type check values
297- [ngx-ow](https://github.com/SamVerschueren/ngx-ow) - Angular form validation on steroids