export function number(rules?: RulesForNumber): NumberSchema;
type RulesForNumber = {
strictType?: boolean;
acceptsSpecialFormats?: boolean;
acceptsFullWidth?: boolean;
map?: string;
ifUndefined?: number | null;
ifEmptyString?: number | null;
ifNull?: number | null;
integer?: boolean | NUMBER.INTEGER;
only?: number[];
minValue?: number | {value: number, adjusts: boolean};
maxValue?: number | {value: number, adjusts: boolean};
transform?: (value: number, fail: () => never) => number;
}
type ErrorHandler = (err: ValueSchemaError) => number | null | never;
interface NumberSchema {
applyTo(value: unknown, onError?: ErrorHandler): number | null
}Applies schema to value.
If an error occurs, this method calls onError (if specified) or throw ValueSchemaError (otherwise).
// should be OK
assert.strictEqual(
vs.number().applyTo(-123),
-123);
// should be adjusted
assert.strictEqual(
vs.number().applyTo("-123"),
-123);
assert.strictEqual(
vs.number().applyTo(true),
1);
assert.strictEqual(
vs.number().applyTo(false),
0);
// should cause error
assert.strictEqual( // catch error by callback function (that returns a value from applyTo() method)
vs.number().applyTo(
"abc",
(err) => 10),
10);
assert.throws( // ... or try-catch syntax
() => vs.number().applyTo("abc"),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});
assert.throws(
() => vs.number().applyTo("true"),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});Enable strict type check. defaults: false
HANDLE WITH CARE!
In URL encoding, all values will be treated as string.
Use this method when your system accepts ONLY JSON encoding (application/json)
// should be adjusted
assert.strictEqual(
vs.number().applyTo("123"),
123);
assert.strictEqual(
vs.number().applyTo(true),
1);
// should cause error
assert.throws(
() => vs.number({strictType: true}).applyTo("123"),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});
assert.throws(
() => vs.number({strictType: true}).applyTo(true),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});Maps the specified value to the properties of the input object.
NOTE: This rule is only available in object.
const schemaObject = {
userId: vs.number({
map: "user_id",
}),
};
const input = { // input values
user_id: 123,
};
assert.deepStrictEqual(
vs.applySchemaObject(schemaObject, input),
{userId: 123});Specifies return value when input value is undefined.
NOTE: {ifUndefined: undefined} is NOT equivalent to {}. The former accepts undefined input value (and keeps it as-is), the latter doesn't.
// should be adjusted
assert.strictEqual(
vs.number({ifUndefined: 1}).applyTo(undefined),
1);
// should cause error
assert.throws(
() => vs.number().applyTo(undefined),
{name: "ValueSchemaError", rule: vs.RULE.UNDEFINED});
// should accept `undefined` value
assert.strictEqual(
vs.number({ifUndefined: undefined}).applyTo(undefined),
undefined);Specifies return value when input value is null.
// should be adjusted
assert.strictEqual(
vs.number({ifNull: 1}).applyTo(null),
1);
// should cause error
assert.throws(
() => vs.number().applyTo(null),
{name: "ValueSchemaError", rule: vs.RULE.NULL});Specifies return value when input value is "".
// should be adjusted
assert.strictEqual(
vs.number({ifEmptyString: 1}).applyTo(""),
1);
// should cause error
assert.throws(
() => vs.number().applyTo(""),
{name: "ValueSchemaError", rule: vs.RULE.EMPTY_STRING});Accepts all special number formats; e.g., "1e+2", "0x100", "0o100", "0b100".
defaults: false
// should be adjusted
assert.strictEqual(
vs.number({acceptsSpecialFormats: true}).applyTo("1e+2"),
100);
assert.strictEqual(
vs.number({acceptsSpecialFormats: true}).applyTo("0x100"),
256);
assert.strictEqual(
vs.number({acceptsSpecialFormats: true}).applyTo("0o100"),
64);
assert.strictEqual(
vs.number({acceptsSpecialFormats: true}).applyTo("0b100"),
4);
// should cause error
assert.throws(
() => vs.number().applyTo("1e+2"),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});Accepts full-width string; e.g., "1234.5", "1234.5".
defaults: false
// should be adjusted
assert.strictEqual(
vs.number({acceptsFullWidth: true}).applyTo("1234.5"),
1234.5);
// should cause error
assert.throws(
() => vs.number().applyTo("1234.5"),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});Limits an input value to integer.
| value | description |
|---|---|
NUMBER.INTEGER.NO (0) / false |
does not limit to integer |
NUMBER.INTEGER.YES (1) / true |
limits to integer, but does not round |
NUMBER.INTEGER.FLOOR (2) |
rounds towards −∞ |
NUMBER.INTEGER.FLOOR_RZ (3) |
rounds towards 0 |
NUMBER.INTEGER.CEIL (4) |
rounds towards +∞ |
NUMBER.INTEGER.CEIL_RI (5) |
rounds towards ∞ |
NUMBER.INTEGER.HALF_UP (6) |
rounds half towards +∞ |
NUMBER.INTEGER.HALF_UP_RZ (7) |
rounds half towards 0 |
NUMBER.INTEGER.HALF_DOWN (8) |
rounds half towards −∞ |
NUMBER.INTEGER.HALF_DOWN_RZ (9) |
rounds half towards 0 |
// should be adjusted
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.FLOOR}).applyTo(3.14),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.FLOOR}).applyTo("3.14"),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.FLOOR}).applyTo(-3.14),
-4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.FLOOR_RZ}).applyTo(3.14),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.FLOOR_RZ}).applyTo(-3.14),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.CEIL}).applyTo(3.14),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.CEIL}).applyTo(-3.14),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.CEIL_RI}).applyTo(3.14),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.CEIL_RI}).applyTo(-3.14),
-4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP}).applyTo(3.49),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP}).applyTo(3.5),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP}).applyTo(-3.5),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP}).applyTo(-3.51),
-4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP_RZ}).applyTo(3.49),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP_RZ}).applyTo(3.5),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP_RZ}).applyTo(-3.49),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_UP_RZ}).applyTo(-3.5),
-4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN}).applyTo(3.5),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN}).applyTo(3.51),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN}).applyTo(-3.49),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN}).applyTo(-3.5),
-4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN_RZ}).applyTo(3.5),
3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN_RZ}).applyTo(3.51),
4);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN_RZ}).applyTo(-3.5),
-3);
assert.strictEqual(
vs.number({integer: vs.NUMBER.INTEGER.HALF_DOWN_RZ}).applyTo(-3.51),
-4);
// should cause error
assert.throws(
() => vs.number({integer: true}).applyTo(3.14),
{name: "ValueSchemaError", rule: vs.RULE.TYPE});
assert.throws(
() => vs.number({integer: vs.NUMBER.INTEGER.YES}).applyTo(3.14), // equivalent to "true"
{name: "ValueSchemaError", rule: vs.RULE.TYPE});Accepts only particular values.
// should be OK
assert.strictEqual(
vs.number({only: [1, 3, 5]}).applyTo(1),
1);
// should cause error
assert.throws(
() => vs.number({only: [1, 3, 5]}).applyTo(2),
{name: "ValueSchemaError", rule: vs.RULE.ONLY});Limits minimum value.
// should be adjusted
assert.strictEqual(
vs.number({minValue: {value: 1, adjusts: true}}).applyTo(0),
1);
// should cause errors
assert.throws(
() => vs.number({minValue: {value: 1, adjusts: false}}).applyTo(0),
{name: "ValueSchemaError", rule: vs.RULE.MIN_VALUE});
assert.throws(
() => vs.number({minValue: 1}).applyTo(0), // shorthand of {value: 1, adjusts: false}
{name: "ValueSchemaError", rule: vs.RULE.MIN_VALUE});Limits maximum value.
// should be adjusted
assert.strictEqual(
vs.number({maxValue: {value: 100, adjusts: true}}).applyTo(101),
100);
// should cause errors
assert.throws(
() => vs.number({maxValue: {value: 100, adjusts: false}}).applyTo(101),
{name: "ValueSchemaError", rule: vs.RULE.MAX_VALUE});
assert.throws(
() => vs.number({maxValue: 100}).applyTo(101), // shorthand of {value: 100, adjusts: false}
{name: "ValueSchemaError", rule: vs.RULE.MAX_VALUE});Transform input value to another.
fail() causes ValueSchemaError.
// should be adjusted
assert.strictEqual(
vs.number({transform: value => value * 2}).applyTo("1"),
2);
// should cause errors
assert.throws(
() => vs.number({transform: (value, fail) => fail()}).applyTo(0),
{name: "ValueSchemaError", rule: vs.RULE.TRANSFORM});