Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // === Branded utility type, probably best to put in another file === //
- declare const __brand: unique symbol;
- type Branded<BaseType, BrandIdentity> = BaseType & {
- readonly [__brand]: BrandIdentity
- }
- // === Define/export some more narrow numeric types === //
- export type I8 = Branded<number, 'I8'>;
- export type I16 = Branded<number, 'I16'>;
- export type I32 = Branded<number, 'I32'>;
- export type I64 = Branded<number, 'I64'>;
- export type I128 = Branded<bigint, 'I128'>;
- export type U8 = Branded<number, 'U8'>;
- export type U16 = Branded<number, 'U16'>;
- export type U32 = Branded<number, 'U32'>;
- export type U64 = Branded<number, 'U64'>;
- export type U128 = Branded<bigint, 'U128'>;
- export type F32 = Branded<number, 'F32'>;
- export type F64 = Branded<number, 'F64'>;
- // === Runtime assertions will be ignored if process.env.NODE_ENV matches this value === //
- const environmentKey = 'production';
- // === Imports === //
- const { NODE_ENV } = process.env;
- const { fround } = Math;
- const {
- isInteger,
- isNaN,
- MIN_SAFE_INTEGER,
- MAX_SAFE_INTEGER
- } = Number;
- // === Type guards === //
- /**
- * Checks if a number is an 8 bit integer
- */
- export function isI8(v: number): v is I8 {
- return isInteger(v) && v >= -128 && v <= 127;
- }
- /**
- * Checks if a number is a 16 bit integer
- */
- export function isI16(v: number): v is I16 {
- return isInteger(v) && v >= -32768 && v <= 32767;
- }
- /**
- * Checks if a number is a 32 bit integer
- */
- export function isI32(v: number): v is I32 {
- return isInteger(v) && v >= -2147483648 && v <= 2147483647;
- }
- /**
- * Checks if a number is a 64 bit integer
- */
- export function isI64(v: number): v is I64 {
- return isInteger(v) && v >= MIN_SAFE_INTEGER && v <= MAX_SAFE_INTEGER;
- }
- /**
- * Checks if a bigint is a 128 bit integer
- */
- export function isI128(v: bigint): v is I128 {
- return typeof v === 'bigint';
- }
- /**
- * Checks if a number is an 8 bit unsigned integer
- */
- export function isU8(v: number): v is U8 {
- return isInteger(v) && v >= 0 && v <= 255;
- }
- /**
- * Checks if a number is a 16 bit unsigned integer
- */
- export function isU16(v: number): v is U16 {
- return isInteger(v) && v >= 0 && v <= 65535;
- }
- /**
- * Checks if a number is a 32 bit unsigned integer
- */
- export function isU32(v: number): v is U32 {
- return isInteger(v) && v >= 0 && v <= 4294967295;
- }
- /**
- * Checks if a number is a 64 bit unsigned integer
- */
- export function isU64(v: number): v is U64 {
- return isInteger(v) && v >= 0 && v <= MAX_SAFE_INTEGER;
- }
- /**
- * Checks if a bigint is a 128 bit unsigned integer
- */
- export function isU128(v: bigint): v is U128 {
- return typeof v === 'bigint' && v >= 0n;
- }
- /**
- * Checks if a number is a 32 bit float
- */
- export function isF32(v: number): v is F32 {
- return typeof v === 'number' && !isNaN(v) && fround(v) === v;
- }
- /**
- * Checks if a number is a 64 bit float
- */
- export function isF64(v: number): v is F64 {
- return typeof v === 'number' && !isNaN(v);
- }
- // === Assertion functions === //
- /**
- * Throws if number is not an 8 bit integer
- */
- export function assertI8(v: number): asserts v is I8 {
- if (!isI8(v)) {
- throw new TypeError(`${v} is not a valid 8-bit integer`);
- }
- }
- /**
- * Throws if number is not a 16 bit integer
- */
- export function assertI16(v: number): asserts v is I16 {
- if (!isI16(v)) {
- throw new TypeError(`${v} is not a valid 16-bit integer`);
- }
- }
- /**
- * Throws if number is not a 32 bit integer
- */
- export function assertI32(v: number): asserts v is I32 {
- if (!isI32(v)) {
- throw new TypeError(`${v} is not a valid 32-bit integer`);
- }
- }
- /**
- * Throws if number is not a 64 bit integer
- */
- export function assertI64(v: number): asserts v is I64 {
- if (!isI64(v)) {
- throw new TypeError(`${v} is not a valid 64-bit integer`);
- }
- }
- /**
- * Throws if bigint is not a 128 bit integer
- */
- export function assertI128(v: bigint): asserts v is I128 {
- if (!isI128(v)) {
- throw new TypeError(`${v} is not a valid 128-bit integer`);
- }
- }
- /**
- * Throws if number is not an 8 bit unsigned integer
- */
- export function assertU8(v: number): asserts v is U8 {
- if (!isU8(v)) {
- throw new TypeError(`${v} is not a valid 8-bit unsigned integer`);
- }
- }
- /**
- * Throws if number is not a 16 bit unsigned integer
- */
- export function assertU16(v: number): asserts v is U16 {
- if (!isU16(v)) {
- throw new TypeError(`${v} is not a valid 16-bit unsigned integer`);
- }
- }
- /**
- * Throws if number is not a 32 bit unsigned integer
- */
- export function assertU32(v: number): asserts v is U32 {
- if (!isU32(v)) {
- throw new TypeError(`${v} is not a valid 32-bit unsigned integer`);
- }
- }
- /**
- * Throws if number is not a 64 bit unsigned integer
- */
- export function assertU64(v: number): asserts v is U64 {
- if (!isU64(v)) {
- throw new TypeError(`${v} is not a valid 64-bit unsigned integer`);
- }
- }
- /**
- * Throws if bigint is not a 128 bit unsigned integer
- */
- export function assertU128(v: bigint): asserts v is U128 {
- if (!isU128(v)) {
- throw new TypeError(`${v} is not a valid 128-bit unsigned integer`);
- }
- }
- /**
- * Throws if number is not a 32 bit float
- */
- export function assertF32(v: number): asserts v is F32 {
- if (!isF32(v)) {
- throw new TypeError(`${v} is not a valid 32-bit float`);
- }
- }
- /**
- * Throws if number is not a 64 bit float
- */
- export function assertF64(v: number): asserts v is F64 {
- if (!isF64(v)) {
- throw new TypeError(`${v} is not a valid 64-bit float`);
- }
- }
- // === Type Casts === //
- /* note:
- These will throw unless process.env.NODE_ENV is set to the given environment key.
- The idea behind this is that build tools like Rollup, Parcel, Vite, etc. can
- strip these `if (NODE_ENV)...` statements out at compile time for the target environment,
- leaving just referentially transparent identity functions behind. Hopefully V8
- and other runtimes can inline these identity functions; as if they were never there.
- */
- /**
- * Casts a number to an 8 bit integer
- */
- export function i8(v: number) {
- if (NODE_ENV !== environmentKey) assertI8(v);
- return v as I8;
- }
- /**
- * Casts a number to a 16 bit integer
- */
- export function i16(v: number) {
- if (NODE_ENV !== environmentKey) assertI16(v);
- return v as I16;
- }
- /**
- * Casts a number to a 32 bit integer
- */
- export function i32(v: number) {
- if (NODE_ENV !== environmentKey) assertI32(v);
- return v as I32;
- }
- /**
- * Casts a number to a 64 bit integer
- */
- export function i64(v: number) {
- if (NODE_ENV !== environmentKey) assertI64(v);
- return v as I64;
- }
- /**
- * Casts a bigint to a 128 bit integer
- */
- export function i128(v: bigint) {
- if (NODE_ENV !== environmentKey) assertI128(v);
- return v as I128;
- }
- /**
- * Casts a number to an 8 bit unsigned integer
- */
- export function u8(v: number) {
- if (NODE_ENV !== environmentKey) assertU8(v);
- return v as U8;
- }
- /**
- * Casts a number to a 16 bit unsigned integer
- */
- export function u16(v: number) {
- if (NODE_ENV !== environmentKey) assertU16(v);
- return v as U16;
- }
- /**
- * Casts a number to a 32 bit unsigned integer
- */
- export function u32(v: number) {
- if (NODE_ENV !== environmentKey) assertU32(v);
- return v as U32;
- }
- /**
- * Casts a number to a 64 bit unsigned integer
- */
- export function u64(v: number) {
- if (NODE_ENV !== environmentKey) assertU64(v);
- return v as U64;
- }
- /**
- * Casts a bigint to a 128 bit unsigned integer
- */
- export function u128(v: bigint) {
- if (NODE_ENV !== environmentKey) assertU128(v);
- return v as U128;
- }
- /**
- * Casts a number to a 32 bit float
- */
- export function f32(v: number) {
- if (NODE_ENV !== environmentKey) assertF32(v);
- return v as F32;
- }
- /**
- * Casts a number to a 64 bit float
- */
- export function f64(v: number) {
- if (NODE_ENV !== environmentKey) assertF64(v);
- return v as F64;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement