UNPKG

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