Advertisement
Guest User

Number Types

a guest
Mar 24th, 2024
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // === Branded utility type, probably best to put in another file === //
  2. declare const __brand: unique symbol;
  3.  
  4. type Branded<BaseType, BrandIdentity> = BaseType & {
  5.   readonly [__brand]: BrandIdentity
  6. }
  7.  
  8. // === Define/export some more narrow numeric types === //
  9. export type I8 = Branded<number, 'I8'>;
  10. export type I16 = Branded<number, 'I16'>;
  11. export type I32 = Branded<number, 'I32'>;
  12. export type I64 = Branded<number, 'I64'>;
  13. export type I128 = Branded<bigint, 'I128'>;
  14.  
  15. export type U8 = Branded<number, 'U8'>;
  16. export type U16 = Branded<number, 'U16'>;
  17. export type U32 = Branded<number, 'U32'>;
  18. export type U64 = Branded<number, 'U64'>;
  19. export type U128 = Branded<bigint, 'U128'>;
  20.  
  21. export type F32 = Branded<number, 'F32'>;
  22. export type F64 = Branded<number, 'F64'>;
  23.  
  24. // === Runtime assertions will be ignored if process.env.NODE_ENV matches this value === //
  25. const environmentKey = 'production';
  26.  
  27. // === Imports === //
  28. const { NODE_ENV } = process.env;
  29. const { fround } = Math;
  30. const {
  31.   isInteger,
  32.   isNaN,
  33.   MIN_SAFE_INTEGER,
  34.   MAX_SAFE_INTEGER
  35. } = Number;
  36.  
  37. // === Type guards === //
  38.  
  39. /**
  40.  * Checks if a number is an 8 bit integer
  41.  */
  42. export function isI8(v: number): v is I8 {
  43.   return isInteger(v) && v >= -128 && v <= 127;
  44. }
  45.  
  46. /**
  47.  * Checks if a number is a 16 bit integer
  48.  */
  49. export function isI16(v: number): v is I16 {
  50.   return isInteger(v) && v >= -32768 && v <= 32767;
  51. }
  52.  
  53. /**
  54.  * Checks if a number is a 32 bit integer
  55.  */
  56. export function isI32(v: number): v is I32 {
  57.   return isInteger(v) && v >= -2147483648 && v <= 2147483647;
  58. }
  59.  
  60. /**
  61.  * Checks if a number is a 64 bit integer
  62.  */
  63. export function isI64(v: number): v is I64 {
  64.   return isInteger(v) && v >= MIN_SAFE_INTEGER && v <= MAX_SAFE_INTEGER;
  65. }
  66.  
  67. /**
  68.  * Checks if a bigint is a 128 bit integer
  69.  */
  70. export function isI128(v: bigint): v is I128 {
  71.   return typeof v === 'bigint';
  72. }
  73.  
  74. /**
  75.  * Checks if a number is an 8 bit unsigned integer
  76.  */
  77. export function isU8(v: number): v is U8 {
  78.   return isInteger(v) && v >= 0 && v <= 255;
  79. }
  80.  
  81. /**
  82.  * Checks if a number is a 16 bit unsigned integer
  83.  */
  84. export function isU16(v: number): v is U16 {
  85.   return isInteger(v) && v >= 0 && v <= 65535;
  86. }
  87.  
  88. /**
  89.  * Checks if a number is a 32 bit unsigned integer
  90.  */
  91. export function isU32(v: number): v is U32 {
  92.   return isInteger(v) && v >= 0 && v <= 4294967295;
  93. }
  94.  
  95. /**
  96.  * Checks if a number is a 64 bit unsigned integer
  97.  */
  98. export function isU64(v: number): v is U64 {
  99.   return isInteger(v) && v >= 0 && v <= MAX_SAFE_INTEGER;
  100. }
  101.  
  102. /**
  103.  * Checks if a bigint is a 128 bit unsigned integer
  104.  */
  105. export function isU128(v: bigint): v is U128 {
  106.   return typeof v === 'bigint' && v >= 0n;
  107. }
  108.  
  109. /**
  110.  * Checks if a number is a 32 bit float
  111.  */
  112. export function isF32(v: number): v is F32 {
  113.   return typeof v === 'number' && !isNaN(v) && fround(v) === v;
  114. }
  115.  
  116. /**
  117.  * Checks if a number is a 64 bit float
  118.  */
  119. export function isF64(v: number): v is F64 {
  120.   return typeof v === 'number' && !isNaN(v);
  121. }
  122.  
  123.  
  124. // === Assertion functions === //
  125.  
  126. /**
  127.  * Throws if number is not an 8 bit integer
  128.  */
  129. export function assertI8(v: number): asserts v is I8 {
  130.   if (!isI8(v)) {
  131.     throw new TypeError(`${v} is not a valid 8-bit integer`);
  132.   }
  133. }
  134.  
  135. /**
  136.  * Throws if number is not a 16 bit integer
  137.  */
  138. export function assertI16(v: number): asserts v is I16 {
  139.   if (!isI16(v)) {
  140.     throw new TypeError(`${v} is not a valid 16-bit integer`);
  141.   }
  142. }
  143.  
  144. /**
  145.  * Throws if number is not a 32 bit integer
  146.  */
  147. export function assertI32(v: number): asserts v is I32 {
  148.   if (!isI32(v)) {
  149.     throw new TypeError(`${v} is not a valid 32-bit integer`);
  150.   }
  151. }
  152.  
  153. /**
  154.  * Throws if number is not a 64 bit integer
  155.  */
  156. export function assertI64(v: number): asserts v is I64 {
  157.   if (!isI64(v)) {
  158.     throw new TypeError(`${v} is not a valid 64-bit integer`);
  159.   }
  160. }
  161.  
  162. /**
  163.  * Throws if bigint is not a 128 bit integer
  164.  */
  165. export function assertI128(v: bigint): asserts v is I128 {
  166.   if (!isI128(v)) {
  167.     throw new TypeError(`${v} is not a valid 128-bit integer`);
  168.   }
  169. }
  170.  
  171. /**
  172.  * Throws if number is not an 8 bit unsigned integer
  173.  */
  174. export function assertU8(v: number): asserts v is U8 {
  175.   if (!isU8(v)) {
  176.     throw new TypeError(`${v} is not a valid 8-bit unsigned integer`);
  177.   }
  178. }
  179.  
  180. /**
  181.  * Throws if number is not a 16 bit unsigned integer
  182.  */
  183. export function assertU16(v: number): asserts v is U16 {
  184.   if (!isU16(v)) {
  185.     throw new TypeError(`${v} is not a valid 16-bit unsigned integer`);
  186.   }
  187. }
  188.  
  189. /**
  190.  * Throws if number is not a 32 bit unsigned integer
  191.  */
  192. export function assertU32(v: number): asserts v is U32 {
  193.   if (!isU32(v)) {
  194.     throw new TypeError(`${v} is not a valid 32-bit unsigned integer`);
  195.   }
  196. }
  197.  
  198. /**
  199.  * Throws if number is not a 64 bit unsigned integer
  200.  */
  201. export function assertU64(v: number): asserts v is U64 {
  202.   if (!isU64(v)) {
  203.     throw new TypeError(`${v} is not a valid 64-bit unsigned integer`);
  204.   }
  205. }
  206.  
  207. /**
  208.  * Throws if bigint is not a 128 bit unsigned integer
  209.  */
  210. export function assertU128(v: bigint): asserts v is U128 {
  211.   if (!isU128(v)) {
  212.     throw new TypeError(`${v} is not a valid 128-bit unsigned integer`);
  213.   }
  214. }
  215.  
  216. /**
  217.  * Throws if number is not a 32 bit float
  218.  */
  219. export function assertF32(v: number): asserts v is F32 {
  220.   if (!isF32(v)) {
  221.     throw new TypeError(`${v} is not a valid 32-bit float`);
  222.   }
  223. }
  224.  
  225. /**
  226.  * Throws if number is not a 64 bit float
  227.  */
  228. export function assertF64(v: number): asserts v is F64 {
  229.   if (!isF64(v)) {
  230.     throw new TypeError(`${v} is not a valid 64-bit float`);
  231.   }
  232. }
  233.  
  234. // === Type Casts === //
  235.  
  236. /* note:
  237.      These will throw unless process.env.NODE_ENV is set to the given environment key.
  238.      The idea behind this is that build tools like Rollup, Parcel, Vite, etc. can
  239.      strip these `if (NODE_ENV)...` statements out at compile time for the target environment,
  240.      leaving just referentially transparent identity functions behind. Hopefully V8
  241.      and other runtimes can inline these identity functions; as if they were never there.
  242. */
  243.  
  244. /**
  245.  * Casts a number to an 8 bit integer
  246.  */
  247. export function i8(v: number) {
  248.   if (NODE_ENV !== environmentKey) assertI8(v);
  249.   return v as I8;
  250. }
  251.  
  252. /**
  253.  * Casts a number to a 16 bit integer
  254.  */
  255. export function i16(v: number) {
  256.   if (NODE_ENV !== environmentKey) assertI16(v);
  257.   return v as I16;
  258. }
  259.  
  260. /**
  261.  * Casts a number to a 32 bit integer
  262.  */
  263. export function i32(v: number) {
  264.   if (NODE_ENV !== environmentKey) assertI32(v);
  265.   return v as I32;
  266. }
  267.  
  268. /**
  269.  * Casts a number to a 64 bit integer
  270.  */
  271. export function i64(v: number) {
  272.   if (NODE_ENV !== environmentKey) assertI64(v);
  273.   return v as I64;
  274. }
  275.  
  276. /**
  277.  * Casts a bigint to a 128 bit integer
  278.  */
  279. export function i128(v: bigint) {
  280.   if (NODE_ENV !== environmentKey) assertI128(v);
  281.   return v as I128;
  282. }
  283.  
  284. /**
  285.  * Casts a number to an 8 bit unsigned integer
  286.  */
  287. export function u8(v: number) {
  288.   if (NODE_ENV !== environmentKey) assertU8(v);
  289.   return v as U8;
  290. }
  291.  
  292. /**
  293.  * Casts a number to a 16 bit unsigned integer
  294.  */
  295. export function u16(v: number) {
  296.   if (NODE_ENV !== environmentKey) assertU16(v);
  297.   return v as U16;
  298. }
  299.  
  300. /**
  301.  * Casts a number to a 32 bit unsigned integer
  302.  */
  303. export function u32(v: number) {
  304.   if (NODE_ENV !== environmentKey) assertU32(v);
  305.   return v as U32;
  306. }
  307.  
  308. /**
  309.  * Casts a number to a 64 bit unsigned integer
  310.  */
  311. export function u64(v: number) {
  312.   if (NODE_ENV !== environmentKey) assertU64(v);
  313.   return v as U64;
  314. }
  315.  
  316. /**
  317.  * Casts a bigint to a 128 bit unsigned integer
  318.  */
  319. export function u128(v: bigint) {
  320.   if (NODE_ENV !== environmentKey) assertU128(v);
  321.   return v as U128;
  322. }
  323.  
  324. /**
  325.  * Casts a number to a 32 bit float
  326.  */
  327. export function f32(v: number) {
  328.   if (NODE_ENV !== environmentKey) assertF32(v);
  329.   return v as F32;
  330. }
  331.  
  332. /**
  333.  * Casts a number to a 64 bit float
  334.  */
  335. export function f64(v: number) {
  336.   if (NODE_ENV !== environmentKey) assertF64(v);
  337.   return v as F64;
  338. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement