to-typed
Version:
Type-guards, casts and converts unknowns into typed values
156 lines • 6.36 kB
JavaScript
import { Utils, Maybe, Cast, Guard } from "./internal.js";
export class Convert extends Cast {
constructor(_convert) {
super((value, s) => Maybe.just(_convert(value, s)));
this._convert = _convert;
}
static lazy(fun) {
return new Convert((val, s) => fun(s)._convert(val, s));
}
convert(value, settings) {
return this._convert(value, settings !== null && settings !== void 0 ? settings : Cast.defaults);
}
decons() {
const def = this.convert(undefined);
if (def !== null && typeof def === 'object' && !(def instanceof Date)) {
const replaceProperty = (key, value) => new Proxy(def, {
get: (...args) => args[1] === key ? value : Reflect.get(...args)
});
const convertGetter = (key) => new Convert((value, settings) => {
const t = this._convert(replaceProperty(key, value), settings);
return t ? t[key] : undefined;
});
return new Proxy(def, {
get: (...args) => {
if (args[0].propertyIsEnumerable(args[1]))
return convertGetter(args[1]);
return Reflect.get(...args);
}
});
}
else
return def;
}
config(config) {
return new Convert((value, s) => this._convert(value, { ...s, ...config }));
}
static toConst(value) {
return new Convert(_ => value);
}
compose(g) {
return new Convert((value, s) => g._convert(this._convert(value, s), s));
}
map(fun) {
return new Convert((value, s) => fun(this._convert(value, s)));
}
/**
* Converts to a union of the given options, and defaults to the first option.
* @param options an array of options to choose from, where the first option is the default
* @returns a `Convert` that converts to a union
*/
static toEnum(...options) {
return Cast.asEnum(...options).else(options[0]);
}
static toString(alt = '') {
return Cast.asString.else(alt);
}
static toNumber(alt = 0) {
return Cast.asNumber.else(alt);
}
static toFinite(alt = 0) {
return Cast.asFinite.else(alt);
}
static toInteger(alt = 0) {
return Cast.asInteger.else(alt);
}
static toBoolean(alt = false) {
return Cast.asBoolean.else(alt);
}
static toTruthy() {
return new Convert(value => !!value);
}
static toBigInt(alt = BigInt(0)) {
return Cast.asBigInt.else(alt);
}
static toDate(alt = new Date(0)) {
return Cast.asDate.else(alt);
}
static get toJSON() {
return new Convert(value => {
try {
return JSON.stringify(value);
}
catch (e) {
return undefined;
}
});
}
static toArray(alt = []) {
return Cast.asArray.else(alt);
}
static toArrayOf(convertItem, alt = []) {
return Cast.asArrayOf(convertItem).else(alt);
}
static toStructOf(convertItem, alt = {}) {
return Cast.asStructOf(convertItem).else(alt);
}
/**
* Given an object or tuple of converts, it produces a convert that outputs an object or tuple having the same shape as the given converts.
* @param casts an object or tuple of converts
* @returns a convert that produces an object or tuple matching the shape of the given converts
*/
static toCollectionLike(converts) {
return Guard.isCollection.or(Cast.just(Array.isArray(converts) ? [] : {})).asCollectionLike(converts).elseThrow();
}
/**
* Produces a convert that filters out values from the input that could not be casted by the given cast.
* @param cast the cast to use for filtering
* @returns a convert that filters out values that could not be casted by the given cast
*/
static toArrayWhere(cast) {
return Cast.asArrayWhere(cast).else([]);
}
/**
* Creates a `Convert` based on the given sample value, which is also used as the set of default values.
* @param alt a sample value which also serves as the set of default values
* @returns a `Convert` based on the given sample value
*/
static to(alt) {
switch (typeof alt) {
case 'string':
return Convert.toString(alt);
case 'number':
return Convert.toNumber(alt);
case 'boolean':
return Convert.toBoolean(alt);
case 'bigint':
return Convert.toBigInt(alt);
case 'symbol':
Guard.isSymbol.else(alt);
case 'function':
return Guard.isFunction.else(alt);
case 'undefined':
return Convert.toConst(undefined);
case 'object':
if (alt instanceof Convert)
return alt;
else if (alt === null)
return Convert.toConst(null);
}
return Convert.toCollectionLike(Utils.mapEager(alt, Convert.to));
}
toEnum(...options) { return this.compose(Convert.toEnum(...options)); }
toString(alt = '') { return this.compose(Convert.toString(alt)); }
toNumber(alt = 0) { return this.compose(Convert.toNumber(alt)); }
toBoolean(alt = false) { return this.compose(Convert.toBoolean(alt)); }
toBigInt(alt = BigInt(0)) { return this.compose(Convert.toBigInt(alt)); }
toDate(alt = new Date(0)) { return this.compose(Convert.toDate(alt)); }
toArray(convertItem, alt = []) { return this.compose(Convert.toArrayOf(convertItem, alt)); }
toArrayOf(convertItem, alt = []) { return this.compose(Convert.toArrayOf(convertItem, alt)); }
toStructOf(convertItem, alt = {}) { return this.compose(Convert.toStructOf(convertItem, alt)); }
toCollectionLike(converts) { return this.compose(Convert.toCollectionLike(converts)); }
toArrayWhere(cast) { return this.compose(Convert.toArrayWhere(cast)); }
to(alt) { return this.compose(Convert.to(alt)); }
}
Convert.id = new Convert(value => value);
//# sourceMappingURL=convert.js.map