UNPKG

ts-prims

Version:
109 lines 4.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Prim = exports.constraintsOf = exports.primTypeOf = exports.superConstraint = exports.display = void 0; /** * Returns a 'display value' string for `v`. * * In case `v` is of type `string`, the returned string will be `v` within * double quotes. Otherwise it will return the result of the built-in to-string * happening naturally when appending primitives to strings in Javascript. * * ```ts * display('Hello, World!') // '"Hello, World"' * display(2 + 5) // '7' * ``` * * @param v The primitive-typed value * @returns The display value string of `v` */ const display = (v) => typeof v == 'string' ? `"${v}"` : `${v}`; exports.display = display; /** * Constraint that the primitive type of two types must be equal for them to be * assignable to one another. This constraint is implied in the type system and * made explicit in the runtime implementation through this object. */ const superConstraint = (pc, v) => typeof v == (0, exports.primTypeOf)(pc) ? undefined : `${(0, exports.display)(v)} is not assignable to type '${pc.name}'.\n` + ` Supertypes do not match: ${typeof v}, ${(0, exports.primTypeOf)(pc)}.`; exports.superConstraint = superConstraint; /** * Returns the underlying type of the given constructor function `pc`. * * This is basically a version of `typeof` that operates, not directly on the * values, but on the constructor function itself. * * @template P The primitive type * @param pc The prim constructor * @returns The underlying type of `pc`: `'boolean'`, `'string'`, * `'number'` or `'bigint'`. */ const primTypeOf = (pc) => 'super' in pc ? (0, exports.primTypeOf)(pc.super) : pc === Boolean ? 'boolean' : pc === String ? 'string' : pc === Number ? 'number' : 'bigint'; exports.primTypeOf = primTypeOf; /** Gets the constraints associated with the constructor `pc` */ const constraintsOf = (pc) => 'super' in pc ? pc.constraints : [exports.superConstraint]; exports.constraintsOf = constraintsOf; /** * Creates a constructor function for a primitive type extending `P`. * * Whenever your type requires runtime presence, the `Prim` function can be * used to create a constructor function for your primitive type, following * the same pattern: * * ```ts * import { type prim, type width, Prim, widthConstraint } from 'ts-prims' * // use the `width` type to constrain the width of `byte` * type byte = prim<number, width<1>> * // use the `widthConstraint` to constrain the width at runtime * const Byte = Prim<byte>('byte', Number, widthConstraint(1)) * let x: byte = Byte(100) // ok * let y: byte = Byte(1000) // runtime error * // TypeError: 1000 is not assignable to 'byte': -128 .. 127 * ``` * * @template P The primitive type * * @param name The name for the type, e.g. `int` * @param pc The parent constructor function, e.g. `Int` or `Number` * @param constraints Optional constraints for the primitive type. Any * constraints from the super constructor will be used automatically * and should not be passed in here again. * * @see {@link PrimFactory} * @see {@link PrimConstructor} * @see {@link NativeConstructor} * @see {@link Constraint} */ const Prim = (name, pc, constraints = []) => { const result = ({ [name]: (v) => result.to(v) })[name]; result.super = pc; constraints = Array.isArray(constraints) ? constraints : constraints ? [constraints] : []; result.constraints = [...(0, exports.constraintsOf)(pc), ...constraints]; result.is = (v) => { for (let constraint of result.constraints) { const err = constraint(result, v); if (err) return false; } return true; }; result.as = (v) => { for (let constraint of result.constraints) { const err = constraint(result, v); if (err) throw new TypeError(err); } }; result.to = (v) => { result.as(v); return v; }; return result; }; exports.Prim = Prim; //# sourceMappingURL=prim.js.map