alwz
v2.9.0
Published
Extendable library for typecasting
Maintainers
Readme
Extendable library for typecasting.
Usage
Types
Guarantee data type
Examples
import { byte, short, int, uint, long, array } from 'alwz';
byte('3'); // 3
short(false); // 0
int(true); // 1
uint(Infinity); // 4294967295
long(NaN); // 0
long(['1', '2', '3']); // 1 | ['1','2','3'] => '1' => 1
array('abc'); // ['abc']Structures
- See: utils
ensure structure for complex data
Examples
normalize array elements
import { utils } from 'alwz';
const arrayOf = utils.array;
const ArrayOfUByte = arrayOf(byte);
ArrayOfUByte([undefined, true, 2.3, '4', Infinity]); // [0, 1, 2, 4, 127]simplify nested arrays processing
const arrayOf = utils.array;
const NestedBytesArray = arrayOf(arrayOf(byte));
NestedBytesArray(1); // [[1]];
NestedBytesArray([[null, NaN, 'a'], [true, '2', 3], Infinity]); // [[[0, 0, 0], [1, 2, 3]], [[127]]];create tuples
const tuple = utils.tuple;
const PairOfUint = tuple([uint, uint]);
PairOfUint([3.5, '100']); // [3, 100]
const PairOfNumbers = tuple([Number, Number]);
PairOfNumbers(['abc', 3.5, 100]); // [NaN, 3.5]Transformations
- See: presets
predefined converters
Examples
build smart bool converter
import { presets } from 'alwz';
const bool = presets.boolean
.clone()
.string(function(v) { // string input processing
if (v === 'true' || v === 'yes') {
return true;
} else if (v === 'false' || v === 'no') {
return false;
} else {
return this.types.number(Number(v));
}
})
.convert;
bool('yes'); // true
bool('no'); // false
bool('false'); // falseparse colon-separated number/string records
const PathArray = presets.array
.clone()
.string((i) => [...i.matchAll(/\/(\w+)/g)].map((i) => i[1]))
.convert;
const DSV2Tuple = utils.tuple(
[String, String, Number, Number, String, PathArray, PathArray],
presets.array
.clone()
.string((i) => i.split(':'))
.convert
);
const input = 'user:12345:1000:1000:ordinar user:/home/user:/bin/sh';
DSV2Tuple(input); // ['user', '12345', 1000, 1000, 'ordinar user', ['home', 'user'], ['bin', 'sh']];converters
deprecated
Selector
dynamically select conversion function at runtime (from predefined list)
Examples
import { to } from 'alwz';
to('int')('24.5'); // 24
to('byte')(Infinity); // 127
to('bigint')('42.5'); // 42nPredicates
- See: is
check data type
Examples
import { is } from 'alwz';
is.void(0); // false
is.void(null); // true
is.value(null); // false
is.value(0); // true
is.ubyte(255); // true
is.int(Infinity); // false
is.object(null); // false
is.Iterable(new Set()); // trueChecks
- See: Is
create type guard functions
Examples
import { Is } from 'alwz';
const isAlphaOrBeta = Is.variant(['Alpha', 'Beta']);
isAlphaOrBeta('Alpha'); // true;
isAlphaOrBeta('Gamma'); // false;
class X {}
class Y extends X {}
const isX = Is.instance(X);
isX(new X); // true
isX(new Y); // true
isX({}); // falseErrors
- See: ErrorValue
create informative errors (ternary-friendly)
Examples
import { ErrorValue } from 'alwz';
const rise = (condition) => condition
? new ErrorValue('oops', { condition, date: Date.now() }).throw()
: condition;
rise(true); // throws ErrorValue with extra message and datapresets
Examples
import presets from 'alwz/presets';
const { boolean, byte, int, string, ... } = presets;boolean
Examples
boolean.convert('abc'); // true
boolean.convert(Symbol.for('')); // false
boolean.convert([]); // false
boolean.convert([0]); // false
boolean.convert([false, true]); // false
boolean.convert([123]); // truenumber
Examples
number.convert(Infinity); // Infinity
number.convert('42'); // 42
number.convert('abc'); // NaN
number.convert(Symbol.for('42')); // 42
number.convert(new Date('1970-01-01T00:00:00.042Z')); // 42
number.convert(['42']); // 42
number.convert([ [ [ 42 ] ] ]); // 42
number.convert(new Date('1970-01-01T00:00:00.999Z')); // 999integers
|--------|------------------|------------------|
| type | min | max |
|--------|------------------|------------------|
| byte | -128 | 127 |
| short | -32768 | 32767 |
| int | -2147483648 | 2147483647 |
| long | MIN_SAFE_INTEGER | MAX_SAFE_INTEGER |
|--------|------------------|------------------|
| ubyte | 0 | 255 |
| ushort | 0 | 65535 |
| uint | 0 | 4294967295 |
| ulong | 0 | MAX_SAFE_INTEGER |
|--------|------------------|------------------|Examples
int.convert(undefined); // 0
int.convert(null); // 0
int.convert(NaN); // 0
int.convert('abc'); // 0
int.convert(true); // 1
int.convert(42.5); // 42
int.convert('42.5'); // 42
int.convert(['42.5']); // 42
int.convert(Symbol.for('42.5')); // 42
int.convert(new Date('1970-01-01T00:00:00.042Z')); // 42
int.convert(new Date(NaN)); // 0signed
cast to byte, short (2 bytes), int (4 bytes) or long (8 bytes)
Examples
byte.convert(128); // 127
byte.convert(Infinity); // 127
byte.convert(-Infinity); // -128
short.convert(Infinity); // 32767
short.convert(-Infinity); // -32768
int.convert(Infinity); // 2147483647
int.convert(-Infinity); // -2147483648
long.convert(Infinity); // MAX_SAFE_INTEGER
long.convert(-Infinity); // MIN_SAFE_INTEGERunsigned
cast to ubyte, ushort (2 bytes), uint (4 bytes) or ulong (8 bytes)
Examples
ubyte.convert(-7); // 0
ubyte.convert('a'); // 0
ubyte.convert(Infinity); // 255
ubyte.convert(-Infinity); // 0
ushort.convert(Infinity); // 65535
ushort.convert(-Infinity); // 0
uint.convert(Infinity); // 4294967295
uint.convert(-Infinity); // 0
ulong.convert(Infinity); // MAX_SAFE_INTEGER
ulong.convert(-Infinity); // 0floats
Examples
double.convert('42.5'); // 42.5
double.convert(Infinity); // Number.MAX_VALUE
double.convert(NaN); // 0bigint
Examples
bigint.convert(42.5); // 42n
bigint.convert('42'); // 42n
bigint.convert('42.5'); // 0n
bigint.convert(Symbol.for('42')); // 42n
bigint.convert(new Date('1970-01-01T00:00:00.999Z')); // 999nstring
Examples
string.convert(); // ''
string.convert(null); // ''
string.convert(false); // ''
string.convert(true); // ' '
string.convert(42.5); // '42.5'
string.convert([1, 2, 3]); // '1'
string.convert(Symbol.for('42')); // '42'
string.convert(new Date('1970-01-01T00:00:00.999Z')); // '1970-01-01T00:00:00.999Z'symbol
Examples
symbol.convert(false); // Symbol('')
symbol.convert(42.5); // Symbol('42.5')
symbol.convert('42.5'); // Symbol('42.5')
symbol.convert([1.5, 2, 3]); // Symbol('1.5')
symbol.convert(new Date('1970-01-01T00:00:00.999Z')); // Symbol('1970-01-01T00:00:00.999Z')array
Examples
array.convert(); // []
array.convert(null); // []
array.convert(false); // [false]
array.convert(123); // [123]
array.convert('1,2,3'); // ['1,2,3']
array.convert(new Set([1, 2, 3])); // [1, 2, 3]
array.convert(new Map([[1, 2], [3, 4], [5, 6]])); // [[1, 2], [3, 4], [5, 6]]fn
Examples
fn.convert((a, b) => a + b); // (a, b) => a + b
fn.convert(123); // () => 123date
Examples
date.convert(111); // Date('1970-01-01T00:00:00.111Z')
date.convert([222, 333]); // Date('1970-01-01T00:00:00.222Z')
date.convert('abc'); // Date(NaN)object
Examples
object.convert(undefined); // {}
object.convert(null); // {}
object.convert(false); // Boolean { false }
object.convert(1); // Number { 1 }
object.convert('2'); // String { 2 }
object.convert([1, '2', 3n]); // [1, '2', 3n]map
Examples
map.convert([ [true, 1], 2, '3']); // Map { [true, 1] }weakmap
Examples
weakmap.convert([ [Boolean, 'bool'], [Number, 'num'], [String, 'str'], [true, 1], 2, '3']); // WeakMap { [Boolean, 'bool'], [Number, 'num'], [String, 'str'] }set
Examples
set.convert([1, '2', 3]); // Set {1, '2', 3}weakset
Examples
weakset.convert([Boolean, Number, String, true, 2, '3']); // WeakSet { Boolean, Number, String }promise
Examples
promise.convert(Promise.resolve(1)); // Promise { 1 }
promise.convert(42); // Promise { 42 }cast
- See: presets
cast functions (based on presets list)
Examples
import cast from 'alwz/cast';
const { byte, ushort, int, long, array } = cast;
byte(true); // 1
ushort(Infinity); // 65535
int('3'); // 3
long(NaN); // 0
long(['1', '2', '3']); // 1 | ['1','2','3'] => '1' => 1
array('abc'); // ['abc']to
Parameters
namestring name of the preset to use for conversion
Examples
to('int')('11.1'); // 11
to('abc'); // Error- Throws ErrorValue if the preset name is unknown
Returns Function conversion function
utils
extra utils functions
Examples
import { array, tuple, ... } from 'alwz/utils';array
constrain data to an array elements of a given type
Parameters
conversionConversion<any, OUTPUT> item conversioninitiatorConversion<any, Array<any>> input data initial conversion (optional, defaultpresets.array.convert)
Examples
const ArrayOfNumbers = array(Number);
ArrayOfNumbers(null); // []
ArrayOfNumbers([]); // []
ArrayOfNumbers([true, 2, '3', {}]); // [1, 2, 3, NaN]sparse arrays behavior
// Be aware of sparse arrays behavior - conversion is not performed for empty items
ArrayOfNumbers([1, , 3]) // [1, , 3]Returns Conversion<any, Array<OUTPUT>>
tuple
constrain data to a tuple with given types
Parameters
conversionsArray<Conversion<any, any>> tuple elemets conversionsinitiatorConversion<any, Array<any>> input data initial conversion (optional, defaultpresets.array.convert)
Examples
const NumStrBool = tuple([Number, String, Boolean]);
NumStrBool(null); // [NaN, 'undefined', false]
NumStrBool([]); // [NaN, '', false]
NumStrBool('5'); // [5, 'undefined', false]
NumStrBool(['1', '2', '3']); // [1, '2', true]Returns Conversion<any, Array<any>>
range
constrain variable value within a given range
Parameters
lowerOUTPUT lower range border (optional, default-Number.MAX_VALUE)upperOUTPUT upper range border (optional, defaultNumber.MAX_VALUE)fallbackFallback<OUTPUT> fallback value generatorinitiatorConversion<any, OUTPUT> input data initial conversion (optional, defaultpresets.double.convert)
Examples
cast to values in range
const range37 = range(3, 7);
range37(5); // 5
range37(1); // 3 (replaced by the minimum possible value)
range37(9); // 7 (replaced by the maximum possible value)custom behavior for out of range values
const range37WithCustomFallback = range(3, 7, () => -1);
range37WithCustomFallback(5); // 5
range37WithCustomFallback(1); // -1
range37WithCustomFallback(9); // -1prohibition of out of range input
const range37Strict = range(3, 7, () => {
throw new Error('out of range input');
});
range37Strict(9); // throws an errornon-numeric comparable elements can be used
const rangeString = range('k', 'w', undefined, String);
rangeString('n'); // n
rangeString('a'); // k
rangeString('z'); // wReturns Conversion<any, OUTPUT>
variant
constrain variable to given variants
Parameters
valuesArray<OUTPUT> valid values listfallbackFallback<OUTPUT> fallback value generator (optional, default()=>values[0])initiatorConversion<any, OUTPUT> input data initial conversion (optional, defaultpresets.double.convert)
Examples
cast to elements from the list only
const oneOf123 = variant([1, 2, 3]);
oneOf123(1); // 1
oneOf123(2); // 2
oneOf123(3); // 3
oneOf123(4); // 1 (replaced by the first element - default behavior)
oneOf123(-5); // 1custom default element
const oneOf123WithCustomFallback = variant([1, 2, 3], () => -1);
oneOf123WithCustomFallback(4); // -1prohibition of unlisted items
oneOf123Strict([1, 2, 3], () => {
throw new Error('invalid input');
});
oneOf123Strict(4); // throws an errornon-numeric elements can be used
const AlphaBetaGamma = variant(['Alpha', 'Beta'], () => 'Gamma', String);
AlphaBetaGamma('Alpha'); // 'Alpha'
AlphaBetaGamma('Beta'); // 'Beta'
AlphaBetaGamma('Gamma'); // 'Gamma'
AlphaBetaGamma('Delta'); // 'Gamma'Returns Conversion<any, OUTPUT>
object
cast data into an object with a given schema
Parameters
schemaRecord<string, Conversion<any, OUTPUT>>initiatorConversion<any, OUTPUT> input data initial conversion (optional, defaultpresets.object.convert)
Examples
const obj = object({
a: ubyte,
b: array(object({
c: int,
d: string,
})),
});
obj(undefined); // { a: 0, b: [] }
obj({ a: 999, b: [{ c: 2.5, d: 3 }, null] }); // { a: 255, b: [{ c: 2, d: '3' }, { c: 0, d: '' }] }Returns Conversion<any, OUTPUT>
dictionary
cast data into a dictionary (object with values of the same type)
Parameters
conversioninitiatorConversion<any, any> input data conversion (optional, defaultpresets.object.convert)
Examples
const dictOfInt = utils.dictionary(int);
dictOfInt(undefined); // { }
dictOfInt({ a: null, b: true, c: '2', d: [3, 4] }); // { a: 0, b: 1, c: 2, d: 3 }Returns Conversion<any, Record<(string | number), VALUE>>
projection
project some data into another according to schema
Parameters
schemaObject
Examples
const schema = {
// shallow element
a: (source) => source.x + 1,
// nested schema
b: {
c: (source) => source.x + 2,
},
// options ( second argument )
d: (source, options) => options,
// mid-process result access
e: (source, options, target) => { target._e = source.x + 3; },
// call context
f: function() { return this; },
};
const project = projection(schema);
const input = { x: 1 };
const options = { z: 5 };
const context = { y: 11 };
project.call(context, input, options);
{
a: 2,
b: { c: 3 },
d: { z: 5 },
_e: 7, e: undefined,
f: { y: 11 },
}Returns Function transform function that can optionally take a context (this) and additional options
is
type guard functions
Examples
import is from 'alwz/is';undefined
Examples
is.undefined() // true
is.undefined(0) // falsenull
Examples
is.null(null) // true
is.null(0) // falsevoid
undefined or null
Examples
is.void(null) // true
is.void(0) // falsevalue
any value except undefined or null
Examples
is.value(null) // false
is.value(0) // trueboolean
Examples
is.boolean(1) // false
is.boolean(true) // truenumber
Examples
is.number(NaN) // true
is.number(Infinity) // true
is.number(1) // true
is.number('1') // falseintegers
byte, short, int, long, ubyte, ushort, uint, ulong
Examples
is.int(NaN) // false
is.uint(-1) // false
is.uint(1) // true
is.uint(1.5) // false
is.long(Infinity) // falsefloats
double
Examples
is.double(NaN) // false
is.double(Infinity) // false
is.double(1.5) // truebigint
string
symbol
function
object
any object (null excluded)
Examples
is.object(null) // false
is.object({}) // trueError
Array
Date
RegExp
Promise
Set
WeakSet
Map
WeakMap
Iterable
can be iterated
Examples
is.Iterable(new Map()); // true
is.Iterable([]); // true
is.Iterable({}); // falseIs
guard function builders
Examples
import Is from 'alwz/Is';type
Parameters
type
Examples
const isString = type('string');
isString(1); // false
isString('1'); // trueinstance
Parameters
prototype
Examples
class Test {}
const isTest = instance(Test);
isTest({}); // false
isTest(new Test()); // truevariant
Parameters
list
Examples
const isVariant = variant([1, 2, 3]);
isVariant(4); // false
isVariant(3); // truecheck
Parameters
guard
Examples
const isOdd = check((v) => v % 2 ? true : false);
isOdd(0); // false
isOdd(1); // trueConverter
converts input data to specific type
- at first checks if conversion is necessary
- attempts conversion based on the input data type
- searches for suitable conversions among registered
- calls a fallback function
Parameters
isIS<OUTPUT> initial input data type check (predicate). determines if any conversion is necessaryfallbackFallback<OUTPUT> fallback value generator. runs if none of the available conversions are suitable
Examples
converter creation
const positive = new Converter(
(input) => typeof input === 'number' && input > 0,
(input) => input === 0 ? 0.1 : 0.2
);
positive
.undefined(() => 0.3)
.boolean((i) => i ? 1 : 0.4)
.number(function(i) {
const result = Math.abs(i)
return this.is(result) ? result : this.fallback(i);
})
.string((i) => positive.convert(Number(i)))
.symbol((i) => positive.convert(Symbol.keyFor(i)))
.bigint((i) => positive.convert(Number(i)))
.register(Array.isArray, (i) => positive.convert(i[0]))
.register((i) => i === null, (i) => 0.5);
positive.convert(1); // 1
positive.convert(0); // 0.1 (fallback)
positive.convert(NaN); // 0.2 (fallback)
positive.convert(undefined); // 0.3 (has own handler)
positive.convert(false); // 0.4 (has own handler)
positive.convert(null); // 0.5 (has own handler)
positive.convert(2n); // 2
positive.convert(-3); // 3
positive.convert('4'); // 4
positive.convert([5, 6]); // 5conversion with prohibited input types
const converter = new Converter(
(input) => typeof input === 'number',
(input) => {
throw new Error('unknown input data type:' + input);
})
.string((i) => {
throw new Error('string input is forbidden:' + i);
})
.boolean(Number)
.register(Array.isArray, (i) => converter.convert(i[0]));
converter.convert(true); // 1
converter.convert(2); // 2
converter.convert('3'); // Error
converter.convert([4]); // 4
converter.convert(Promise.resolve(5)); // Errorconvert
converts data according to saved conversion rules
Parameters
inputany input data
register
adds conversion function for INPUT type
Parameters
isIS<INPUT> input data type check (predicate), determines if input can be processed byconversionconversionConversion<INPUT, OUTPUT>INPUTtoOUTPUTconversion function
unregister
removes conversion for INPUT type
Parameters
isIS<INPUT> input type check (predicate)
type
set conversion rule for type name if conversion is defined or unset if undefined
Parameters
namestring one of types (typeofresult)conversionConversion?
undefined
conversion rule setter for undefined input
Parameters
conversionConversion?
boolean
conversion rule setter for boolean input
Parameters
conversionConversion?
number
conversion rule setter for number input
Parameters
conversionConversion?
bigint
conversion rule setter for bigint input
Parameters
conversionConversion?
string
conversion rule setter for string input
Parameters
conversionConversion?
symbol
conversion rule setter for symbol input
Parameters
conversionConversion?
clone
Examples
const converter = new Converter(
(i) => typeof i === 'number',
() => 0
)
.undefined(() => 1);
const clone = converter
.clone()
.undefined(() => 2);
converter.convert(); // 1
clone.convert(); // 2ErrorValue
Extends Error
Error with value property (informative errors)
Parameters
messagestring?valueany?optionsany?
Properties
valueany? additional cause info
Examples
generate errors with additional info
throw new ErrorValue('invalid list', { data: 'some additional data' });intercept and wrap thrown error
try {
throw new Error('oops, something went wrong');
} catch (error) {
throw new ErrorValue('urgent message', { data: 'some additional data' }, { cause: error });
}throw
throw this error instance (ternary-friendly)
Examples
const inc = (input) => typeof input === 'number'
? input + 1
: new ErrorValue('invalid list', { input, date: Date.now() }).throw();
inc('1'); // throws ErrorValue