alwz
v2.8.0
Published
Extendable library for typecasting
Downloads
1,572
Maintainers
Readme
Extendable library for typecasting.
Usage
Import
Examples
import * as a from 'alwz';
// or
const a = require('alwz');
Types
- See: presets
convert data with presetted converters
Examples
a.byte('3'); // 3
a.short(false); // 0
a.int(true); // 1
a.uint(Infinity); // 4294967295
a.long(NaN); // 0
a.long(['1', '2', '3']); // 1 | ['1','2','3'] => '1' => 1
a.array('abc'); // ['abc']
a.array([123, 'abc', {}, Math.max]); // [123, 'abc', {}, Math.max]
Structures
- See: utils
construct complex data
Examples
ensure an array output
const array = a.utils.array;
const ArrayOfUByte = array(a.ubyte);
ArrayOfUByte([undefined, true, 2.3, '4', Infinity]); // [0, 1, 2, 4, 255]
simplify multidimensional arrays processing
const array = a.utils.array;
const Bytes3dArray = array(array(array(a.byte)));
Bytes3dArray(1); // [[[1]]];
Bytes3dArray([[[null, NaN, 'a'], [true, '2', 3]], [[Infinity]]]); // [[[0, 0, 0], [1, 2, 3]], [[127]]];
create tuples
const tuple = a.utils.tuple;
const PairOfUint = tuple([a.uint, a.uint]);
PairOfUint(['abc', 3.5, 100]); // [0, 3]
const PairOfNumbers = tuple([Number, Number]);
PairOfNumbers(['abc', 3.5, 100]); // [NaN, 3.5]
Transformations
- See: Converter
create custom converters
Examples
extend an existing converter
// make boolean smarter
const bool = a.converters.get('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'); // false
parse colon-separated number/string records
const PathArray = a.converters.get('array')
.clone()
.string((i) => [...i.matchAll(/\/(\w+)/g)].map((i) => i[1]))
.convert;
const DSV2Tuple = a.utils.tuple(
[String, String, Number, Number, String, PathArray, PathArray],
a.converters.get('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']];
Selector
dynamically select convert function (based on predefined converters)
Examples
a.to('int')('24.5'); // 24
a.to('byte')(Infinity); // 127
a.to('bigint')('42.5'); // 42n
Converters
registry of predefined converters
Examples
// get list of predefined converters
Array.from(a.converters.keys()); // ['boolean', 'byte', 'int', 'long', 'double', 'string', ...];
// retrieving with existence check
const Num = a.converters.converter('number'); // Converter<number>
const Str = a.converters.converter('string'); // Converter<string>
a.converters.converter('123'); // Error
// direct retrieving
const Arr = a.converters.get('array'); // Converter<Array>
const Unknown = a.converters.get('123'); // undefined
Predicates
- See: is
data type checks
Examples
const { is } = a;
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()); // true
Checks
- See: Is
create readable check functions
Examples
const { Is } = a;
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({}); // false
Errors
- See: ErrorValue
create informative errors
Examples
add additional value to an error
const { ErrorValue } = a;
const inc = (input) => typeof input === 'number'
? input + 1
: new ErrorValue('invalid list', { input, date: Date.now() }).throw();
inc('1'); // Error { message: 'invalid number', value: { input: '1', date: 946684800000 } }
intercept and wrap thrown ones
try {
throw new Error('oops, something went wrong');
} catch (error) {
throw new ErrorValue('urgent message', { data: 'some additional data' }, { cause: error });
}
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]); // true
number
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')); // 999
integers
|--------|------------------|------------------|
| 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)); // 0
signed
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_INTEGER
unsigned
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); // 0
double
Examples
double.convert('42.5'); // 42.5
double.convert(Infinity); // Number.MAX_VALUE
double.convert(NaN); // 0
bigint
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')); // 999n
string
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); // () => 123
date
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 }
utils
extra utils functions
Examples
const { array, tuple, range, variant, object, dictionary } = a.utils;
array
constrain data to an array elements of a given type
Parameters
conversion
Conversion<any, OUTPUT> item conversioninitiator
Conversion<any, Array<any>> input data initial conversion (optional, defaultpresets.array.convert
)
Examples
const Numbers = array(Number);
Numbers(); // []
Numbers([]); // []
Numbers([true, 2, "3", {}]); // [1, 2, 3, NaN]
sparse arrays behavior
// Be aware of sparse arrays behavior - conversion is not performed for empty items
numArray[1, , 3] // [1, , 3]
Returns Conversion<any, Array<OUTPUT>>
tuple
constrain data to a tuple with given types
Parameters
conversions
Array<Conversion<any, any>> tuple elemets conversionsinitiator
Conversion<any, Array<any>> input data initial conversion (optional, defaultpresets.array.convert
)
Examples
const NumStrBool = tuple([Number, String, Boolean]);
NumStrBool(); // [NaN, 'undefined', false]
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
lower
OUTPUT lower range border (optional, default-Number.MAX_VALUE
)upper
OUTPUT upper range border (optional, defaultNumber.MAX_VALUE
)fallback
Fallback<OUTPUT> fallback value generatorconversion
Conversion<any, OUTPUT> input data conversion (optional, defaultpresets.double.convert
)
Examples
const range37 = range(3, 7);
range37(1); // 3
range37(5); // 5
range37(9); // 7
const range37WithCustomFallback = range(3, 7, () => -1);
range37WithCustomFallback(1); // -1
range37WithCustomFallback(5); // 5
range37WithCustomFallback(9); // -1
const rangeString = range('k', 'w', undefined, String);
rangeString('a'); // k
rangeString('n'); // n
rangeString('z'); // w
Returns Conversion<any, OUTPUT>
variant
constrain variable to given variants
Parameters
values
Array<OUTPUT> valid values listfallback
Fallback<OUTPUT> fallback value generator (optional, default()=>values[0]
)conversion
Conversion<any, OUTPUT> input data conversion (optional, defaultpresets.double.convert
)
Examples
const oneOf123 = variant([1, 2, 3]);
oneOf123(1); // 1
oneOf123(2); // 2
oneOf123(3); // 3
oneOf123(4); // 1
oneOf123(-5); // 1
const oneOf123WithCustomFallback = variant([1, 2, 3], () => -1);
oneOf123WithCustomFallback(4); // -1
oneOf123Strict([1, 2, 3], () => {
throw new Error('invalid input');
});
oneOf123Strict(4); // throws an Error
const oneOfAB = variant(['a', 'b'], (i) => ['a', 'b'][i], String);
oneOfAB('a'); // 'a'
oneOfAB('b'); // 'b'
oneOfAB(0); // 'a'
oneOfAB(1); // 'b'
Returns Conversion<any, OUTPUT>
object
cast data into an object with a given schema
Parameters
schema
Record<string, Conversion<any, OUTPUT>>conversion
Conversion<any, OUTPUT> input data conversion (optional, defaultpresets.object.convert
)
Examples
const obj = object({
a: a.ubyte,
b: array(object({
c: a.int,
d: a.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
Parameters
conversion
initiator
Conversion<any, any> input data conversion (optional, defaultpresets.object.convert
)
Examples
const dictOfInt = utils.dictionary(a.int);
dictOfInt(undefined); // { }
dictInt({ 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 data into object according to schema
Parameters
schema
Schema
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 reshape = project(schema);
const source = { x: 1 };
const options = { z: 5 };
const context = { y: 11 };
project.call(context, source, options);
{
a: 2,
b: { c: 3 },
d: { z: 5 },
_e: 7, e: undefined,
f: { y: 11 },
}
Returns Function
is
guard functions (pattern matching check)
undefined
null
void
undefined or null
Examples
is.void(null) // true
is.void(0) // false
value
any value except undefined or null
Examples
is.value(null) // false
is.value(0) // true
boolean
Examples
is.boolean(1) // false
is.boolean(true) // true
number
Examples
is.number(NaN) // true
is.number(Infinity) // true
is.number(1) // true
is.number('1') // false
integers
byte, short, int, long
Examples
is.int(NaN) // false
is.long(Infinity) // false
is.uint(-1) // false
is.uint(1) // true
is.uint(1.5) // false
floats
double
Examples
is.double(NaN) // false
is.double(Infinity) // false
is.double(1.5) // true
bigint
string
symbol
function
object
any object (null excluded)
Examples
is.object(null) // false
is.object({}) // true
Error
Array
Examples
is.Array({}) // false
is.Array([]) // true
Date
RegExp
Promise
Set
WeakSet
Map
WeakMap
Iterable
can be iterated
Examples
is.Iterable(new Map()); // true
is.Iterable([]); // true
is.Iterable({}); // false
type
Parameters
type
Examples
const isString = type('string');
isString(1); // false
isString('1'); // true
instance
Parameters
prototype
Examples
class Test {}
const isTest = instance(Test);
isTest({}); // false
isTest(new Test()); // true
variant
Parameters
list
Examples
const isVariant = variant([1, 2, 3]);
isVariant(4); // false
isVariant(3); // true
check
Parameters
guard
Examples
const isOdd = check((v) => v % 2 ? true : false);
isOdd(0); // false
isOdd(1); // true
Converter
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
is
IS<OUTPUT> initial input data type check (predicate). determines if any conversion is necessaryfallback
Fallback<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]); // 5
conversion 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)); // Error
convert
converts data according to saved conversion rules
Parameters
input
any input data
register
adds conversion function for INPUT
type
Parameters
is
IS<INPUT> input data type check (predicate), determines if input can be processed byconversion
conversion
Conversion<INPUT, OUTPUT>INPUT
toOUTPUT
conversion function
unregister
removes conversion for INPUT
type
Parameters
is
IS<INPUT> input type check (predicate)
type
set conversion rule for type name
if conversion
is defined or unset if undefined
Parameters
name
string one of types (typeof
result)conversion
Conversion?
undefined
conversion rule setter for undefined
input
Parameters
conversion
Conversion?
boolean
conversion rule setter for boolean
input
Parameters
conversion
Conversion?
number
conversion rule setter for number
input
Parameters
conversion
Conversion?
bigint
conversion rule setter for bigint
input
Parameters
conversion
Conversion?
string
conversion rule setter for string
input
Parameters
conversion
Conversion?
symbol
conversion rule setter for symbol
input
Parameters
conversion
Conversion?
clone
Examples
const converter = new Converter(
(i) => typeof i === 'number',
() => 0
)
.undefined(() => 1);
const clone = converter
.clone()
.undefined(() => 2);
converter.convert(); // 1
clone.convert(); // 2
ErrorValue
Extends Error
Error with value property
Parameters
message
string?value
any?options
any?
Properties
value
any? can be used to store additional cause info
throw
throw this instance of error