Skip to content

Commit 7b7821a

Browse files
ifiokjrajsaraujo
andauthored
Add nonempty refinement (ianstormtaylor#946)
* feat: create not empty refinement * docs: add not empty to refinements docs * refactor: rename `notEmpty` to `nonempty` Co-authored-by: Allan Juan <[email protected]>
1 parent 9000ed2 commit 7b7821a

File tree

3 files changed

+70
-23
lines changed

3 files changed

+70
-23
lines changed

docs/reference/refinements.md

+18-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ empty(array())
1818

1919
> 🤖 Technically this is the same as using [`size`](#size) of zero, but "empty" feels slightly nicer and will give a slightly easier to read error.
2020
21+
### `max`
22+
23+
```ts
24+
max(number(), 0)
25+
```
26+
27+
```txt
28+
-1
29+
```
30+
31+
`max` enforces that a `number` struct is less than a threshold.
32+
33+
> 🤖 If you need an exclusive maxmimum you can pass `{ exclusive: true }` as the third argument, like `max(number(), 0, { exclusive: true })` for negative numbers.
34+
2135
### `min`
2236

2337
```ts
@@ -32,19 +46,14 @@ min(number(), 9000)
3246

3347
> 🤖 If you need an exclusive minimum you can pass `{ exclusive: true }` as the third argument, like `min(number(), 0, { exclusive: true })` for positive numbers.
3448
35-
### `max`
49+
### `nonempty`
3650

3751
```ts
38-
max(number(), 0)
52+
nonempty(string())
53+
nonempty(array())
3954
```
4055

41-
```txt
42-
-1
43-
```
44-
45-
`max` enforces that a `number` struct is less than a threshold.
46-
47-
> 🤖 If you need an exclusive maxmimum you can pass `{ exclusive: true }` as the third argument, like `max(number(), 0, { exclusive: true })` for negative numbers.
56+
`nonempty` enforces that a string, array, map, or set is not empty. This does the opposite of `empty`.
4857

4958
### `pattern`
5059

src/structs/refinements.ts

+30-14
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,23 @@ export function empty<
99
T extends string | any[] | Map<any, any> | Set<any>,
1010
S extends any
1111
>(struct: Struct<T, S>): Struct<T, S> {
12-
const expected = `Expected an empty ${struct.type}`
13-
1412
return refine(struct, 'empty', (value) => {
15-
if (value instanceof Map || value instanceof Set) {
16-
const { size } = value
17-
return (
18-
size === 0 || `${expected} but received one with a size of \`${size}\``
19-
)
20-
} else {
21-
const { length } = value as string | any[]
22-
return (
23-
length === 0 ||
24-
`${expected} but received one with a length of \`${length}\``
25-
)
26-
}
13+
const size = getSize(value)
14+
return (
15+
size === 0 ||
16+
`Expected an empty ${struct.type} but received one with a size of \`${size}\``
17+
)
2718
})
2819
}
2920

21+
function getSize(value: string | any[] | Map<any, any> | Set<any>): number {
22+
if (value instanceof Map || value instanceof Set) {
23+
return value.size
24+
} else {
25+
return value.length
26+
}
27+
}
28+
3029
/**
3130
* Ensure that a number or date is below a threshold.
3231
*/
@@ -70,6 +69,23 @@ export function min<T extends number | Date, S extends any>(
7069
}${threshold} but received \`${value}\``
7170
})
7271
}
72+
73+
/**
74+
* Ensure that a string, array, map or set is not empty.
75+
*/
76+
77+
export function nonempty<
78+
T extends string | any[] | Map<any, any> | Set<any>,
79+
S extends any
80+
>(struct: Struct<T, S>): Struct<T, S> {
81+
return refine(struct, 'nonempty', (value) => {
82+
const size = getSize(value)
83+
return (
84+
size > 0 || `Expected a nonempty ${struct.type} but received an empty one`
85+
)
86+
})
87+
}
88+
7389
/**
7490
* Ensure that a string matches a regular expression.
7591
*/

test/typings/nonempty.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { assert, nonempty, string, array, map, set } from '../../lib'
2+
import { test } from '..'
3+
4+
test<string>((x) => {
5+
assert(x, nonempty(string()))
6+
return x
7+
})
8+
9+
test<Array<unknown>>((x) => {
10+
assert(x, nonempty(array()))
11+
return x
12+
})
13+
14+
test<Set<unknown>>((x) => {
15+
assert(x, nonempty(set()))
16+
return x
17+
})
18+
19+
test<Map<unknown, unknown>>((x) => {
20+
assert(x, nonempty(map()))
21+
return x
22+
})

0 commit comments

Comments
 (0)