Skip to content

Commit 533f8a2

Browse files
chore: implement double validation
1 parent 3e94a53 commit 533f8a2

File tree

5 files changed

+129
-3
lines changed

5 files changed

+129
-3
lines changed

src/types/double.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { DoubleValidator } from '../validators/double'
2+
import type { LengthValidator, Validator } from './base'
3+
4+
export interface DoubleValidatorType extends Validator<number>, LengthValidator<DoubleValidator> {
5+
positive: () => DoubleValidator
6+
negative: () => DoubleValidator
7+
divisibleBy: (divisor: number) => DoubleValidator
8+
custom: (fn: (value: number | null | undefined) => boolean, message: string) => DoubleValidator
9+
}

src/types/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { BooleanValidatorType } from './boolean'
55
import type { CustomValidatorType } from './custom'
66
import type { DatetimeValidatorType, DateValidatorType } from './date'
77
import type { DecimalValidatorType } from './decimal'
8+
import type { DoubleValidatorType } from './double'
89
import type { EnumValidatorType } from './enum'
910
import type { FloatValidatorType } from './float'
1011
import type { IntegerValidatorType } from './integer'
@@ -29,8 +30,8 @@ export * from './boolean'
2930
export * from './custom'
3031
export * from './date'
3132
export * from './decimal'
33+
export * from './double'
3234
export * from './enum'
33-
export * from './float'
3435

3536
export * from './float'
3637
export * from './integer'
@@ -64,6 +65,7 @@ export interface ValidationInstance {
6465
unix: () => UnixValidatorType
6566
password: () => PasswordValidatorType
6667
float: () => FloatValidatorType
68+
double: () => DoubleValidatorType
6769
decimal: () => DecimalValidatorType
6870
time: () => TimeValidatorType
6971
smallint: () => SmallintValidatorType

src/validators/double.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import type { DoubleValidatorType, ValidationNames } from '../types'
2+
import isDivisibleBy from '../lib/isDivisibleBy'
3+
import { NumberValidator } from './numbers'
4+
5+
export class DoubleValidator extends NumberValidator implements DoubleValidatorType {
6+
public name: ValidationNames = 'float'
7+
8+
constructor() {
9+
super()
10+
// Override the base number validation to ensure it's a float
11+
// Remove the existing number rule and add our own
12+
this.rules = this.rules.filter(rule => rule.name !== 'number')
13+
this.addRule({
14+
name: 'double',
15+
test: (value: unknown): value is number => {
16+
// First check if it's a number
17+
if (typeof value !== 'number' || Number.isNaN(value)) {
18+
return false
19+
}
20+
// All numbers in JavaScript are floats, including Infinity
21+
return true
22+
},
23+
message: 'Must be a valid float number',
24+
})
25+
}
26+
27+
min(min: number): this {
28+
return this.addRule({
29+
name: 'min',
30+
test: (value: number) => {
31+
if (typeof value !== 'number')
32+
return false
33+
return value >= min
34+
},
35+
message: 'Must be at least {min}',
36+
params: { min },
37+
})
38+
}
39+
40+
max(max: number): this {
41+
return this.addRule({
42+
name: 'max',
43+
test: (value: number) => {
44+
if (typeof value !== 'number')
45+
return false
46+
return value <= max
47+
},
48+
message: 'Must be at most {max}',
49+
params: { max },
50+
})
51+
}
52+
53+
length(length: number): this {
54+
return this.addRule({
55+
name: 'length',
56+
test: (value: number) => {
57+
if (typeof value !== 'number')
58+
return false
59+
return value.toString().length === length
60+
},
61+
message: 'Must be exactly {length} digits',
62+
params: { length },
63+
})
64+
}
65+
66+
positive(): this {
67+
return this.addRule({
68+
name: 'positive',
69+
test: (value: number) => {
70+
if (typeof value !== 'number')
71+
return false
72+
return value > 0
73+
},
74+
message: 'Must be a positive number',
75+
})
76+
}
77+
78+
negative(): this {
79+
return this.addRule({
80+
name: 'negative',
81+
test: (value: number) => {
82+
if (typeof value !== 'number')
83+
return false
84+
return value < 0
85+
},
86+
message: 'Must be a negative number',
87+
})
88+
}
89+
90+
divisibleBy(divisor: number): this {
91+
return this.addRule({
92+
name: 'divisibleBy',
93+
test: (value: number) => {
94+
if (typeof value !== 'number')
95+
return false
96+
return isDivisibleBy(String(value), divisor)
97+
},
98+
message: 'Must be divisible by {divisor}',
99+
params: { divisor },
100+
})
101+
}
102+
103+
custom(fn: (value: number) => boolean, message: string): this {
104+
return this.addRule({
105+
name: 'custom',
106+
test: fn,
107+
message,
108+
})
109+
}
110+
}
111+
112+
// Export a function to create float validators
113+
export function float(): DoubleValidator {
114+
return new DoubleValidator()
115+
}

src/validators/float.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export class FloatValidator extends NumberValidator implements FloatValidatorTyp
1111
// Remove the existing number rule and add our own
1212
this.rules = this.rules.filter(rule => rule.name !== 'number')
1313
this.addRule({
14-
name: 'number',
14+
name: 'float',
1515
test: (value: unknown): value is number => {
1616
// First check if it's a number
1717
if (typeof value !== 'number' || Number.isNaN(value)) {

src/validators/integer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export class IntegerValidator extends NumberValidator implements IntegerValidato
1010
// Remove the existing number rule and add our own
1111
this.rules = this.rules.filter(rule => rule.name !== 'number')
1212
this.addRule({
13-
name: 'number',
13+
name: 'integer',
1414
test: (value: number) => {
1515
// First check if it's a number
1616
if (typeof value !== 'number' || Number.isNaN(value) || !Number.isFinite(value)) {

0 commit comments

Comments
 (0)