ts-data-forge 11.0.1 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/README.md +2 -2
  2. package/dist/number/branded-types/int16.d.mts +12 -7
  3. package/dist/number/branded-types/int16.d.mts.map +1 -1
  4. package/dist/number/branded-types/int16.mjs +13 -8
  5. package/dist/number/branded-types/int16.mjs.map +1 -1
  6. package/dist/number/branded-types/int32.d.mts +12 -7
  7. package/dist/number/branded-types/int32.d.mts.map +1 -1
  8. package/dist/number/branded-types/int32.mjs +13 -8
  9. package/dist/number/branded-types/int32.mjs.map +1 -1
  10. package/dist/number/branded-types/negative-finite-number.d.mts +13 -6
  11. package/dist/number/branded-types/negative-finite-number.d.mts.map +1 -1
  12. package/dist/number/branded-types/negative-finite-number.mjs +15 -8
  13. package/dist/number/branded-types/negative-finite-number.mjs.map +1 -1
  14. package/dist/number/branded-types/negative-int.d.mts +11 -6
  15. package/dist/number/branded-types/negative-int.d.mts.map +1 -1
  16. package/dist/number/branded-types/negative-int.mjs +13 -8
  17. package/dist/number/branded-types/negative-int.mjs.map +1 -1
  18. package/dist/number/branded-types/negative-safe-int.d.mts +13 -7
  19. package/dist/number/branded-types/negative-safe-int.d.mts.map +1 -1
  20. package/dist/number/branded-types/negative-safe-int.mjs +15 -9
  21. package/dist/number/branded-types/negative-safe-int.mjs.map +1 -1
  22. package/dist/number/branded-types/non-negative-finite-number.d.mts +11 -6
  23. package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -1
  24. package/dist/number/branded-types/non-negative-finite-number.mjs +12 -7
  25. package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -1
  26. package/dist/number/branded-types/non-negative-int16.d.mts +13 -7
  27. package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -1
  28. package/dist/number/branded-types/non-negative-int16.mjs +14 -8
  29. package/dist/number/branded-types/non-negative-int16.mjs.map +1 -1
  30. package/dist/number/branded-types/non-negative-int32.d.mts +13 -7
  31. package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -1
  32. package/dist/number/branded-types/non-negative-int32.mjs +14 -8
  33. package/dist/number/branded-types/non-negative-int32.mjs.map +1 -1
  34. package/dist/number/branded-types/non-positive-finite-number.d.mts +11 -6
  35. package/dist/number/branded-types/non-positive-finite-number.d.mts.map +1 -1
  36. package/dist/number/branded-types/non-positive-finite-number.mjs +12 -7
  37. package/dist/number/branded-types/non-positive-finite-number.mjs.map +1 -1
  38. package/dist/number/branded-types/non-positive-int.d.mts +11 -6
  39. package/dist/number/branded-types/non-positive-int.d.mts.map +1 -1
  40. package/dist/number/branded-types/non-positive-int.mjs +12 -7
  41. package/dist/number/branded-types/non-positive-int.mjs.map +1 -1
  42. package/dist/number/branded-types/non-positive-safe-int.d.mts +14 -7
  43. package/dist/number/branded-types/non-positive-safe-int.d.mts.map +1 -1
  44. package/dist/number/branded-types/non-positive-safe-int.mjs +15 -8
  45. package/dist/number/branded-types/non-positive-safe-int.mjs.map +1 -1
  46. package/dist/number/branded-types/non-zero-int16.d.mts +13 -7
  47. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -1
  48. package/dist/number/branded-types/non-zero-int16.mjs +14 -8
  49. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -1
  50. package/dist/number/branded-types/non-zero-int32.d.mts +13 -7
  51. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -1
  52. package/dist/number/branded-types/non-zero-int32.mjs +14 -8
  53. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -1
  54. package/dist/number/branded-types/non-zero-safe-int.d.mts +13 -7
  55. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -1
  56. package/dist/number/branded-types/non-zero-safe-int.mjs +14 -8
  57. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -1
  58. package/dist/number/branded-types/non-zero-uint16.d.mts +13 -7
  59. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -1
  60. package/dist/number/branded-types/non-zero-uint16.mjs +14 -8
  61. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -1
  62. package/dist/number/branded-types/non-zero-uint32.d.mts +13 -7
  63. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -1
  64. package/dist/number/branded-types/non-zero-uint32.mjs +14 -8
  65. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -1
  66. package/dist/number/branded-types/positive-finite-number.d.mts +13 -6
  67. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
  68. package/dist/number/branded-types/positive-finite-number.mjs +14 -7
  69. package/dist/number/branded-types/positive-finite-number.mjs.map +1 -1
  70. package/dist/number/branded-types/positive-int.d.mts +13 -8
  71. package/dist/number/branded-types/positive-int.d.mts.map +1 -1
  72. package/dist/number/branded-types/positive-int.mjs +14 -9
  73. package/dist/number/branded-types/positive-int.mjs.map +1 -1
  74. package/dist/number/branded-types/positive-int16.d.mts +13 -7
  75. package/dist/number/branded-types/positive-int16.d.mts.map +1 -1
  76. package/dist/number/branded-types/positive-int16.mjs +14 -8
  77. package/dist/number/branded-types/positive-int16.mjs.map +1 -1
  78. package/dist/number/branded-types/positive-int32.d.mts +13 -7
  79. package/dist/number/branded-types/positive-int32.d.mts.map +1 -1
  80. package/dist/number/branded-types/positive-int32.mjs +14 -8
  81. package/dist/number/branded-types/positive-int32.mjs.map +1 -1
  82. package/dist/number/branded-types/positive-safe-int.d.mts +16 -10
  83. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -1
  84. package/dist/number/branded-types/positive-safe-int.mjs +17 -11
  85. package/dist/number/branded-types/positive-safe-int.mjs.map +1 -1
  86. package/dist/number/branded-types/positive-uint16.d.mts +13 -7
  87. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -1
  88. package/dist/number/branded-types/positive-uint16.mjs +14 -8
  89. package/dist/number/branded-types/positive-uint16.mjs.map +1 -1
  90. package/dist/number/branded-types/positive-uint32.d.mts +13 -7
  91. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -1
  92. package/dist/number/branded-types/positive-uint32.mjs +14 -8
  93. package/dist/number/branded-types/positive-uint32.mjs.map +1 -1
  94. package/dist/number/branded-types/safe-int.d.mts +15 -10
  95. package/dist/number/branded-types/safe-int.d.mts.map +1 -1
  96. package/dist/number/branded-types/safe-int.mjs +16 -11
  97. package/dist/number/branded-types/safe-int.mjs.map +1 -1
  98. package/dist/number/branded-types/safe-uint.d.mts +12 -7
  99. package/dist/number/branded-types/safe-uint.d.mts.map +1 -1
  100. package/dist/number/branded-types/safe-uint.mjs +13 -8
  101. package/dist/number/branded-types/safe-uint.mjs.map +1 -1
  102. package/dist/number/branded-types/uint.d.mts +14 -10
  103. package/dist/number/branded-types/uint.d.mts.map +1 -1
  104. package/dist/number/branded-types/uint.mjs +15 -11
  105. package/dist/number/branded-types/uint.mjs.map +1 -1
  106. package/dist/number/branded-types/uint16.d.mts +12 -7
  107. package/dist/number/branded-types/uint16.d.mts.map +1 -1
  108. package/dist/number/branded-types/uint16.mjs +13 -8
  109. package/dist/number/branded-types/uint16.mjs.map +1 -1
  110. package/dist/number/branded-types/uint32.d.mts +12 -7
  111. package/dist/number/branded-types/uint32.d.mts.map +1 -1
  112. package/dist/number/branded-types/uint32.mjs +13 -8
  113. package/dist/number/branded-types/uint32.mjs.map +1 -1
  114. package/dist/number/enum/int8.d.mts +12 -7
  115. package/dist/number/enum/int8.d.mts.map +1 -1
  116. package/dist/number/enum/int8.mjs +19 -14
  117. package/dist/number/enum/int8.mjs.map +1 -1
  118. package/dist/number/enum/uint8.d.mts +12 -7
  119. package/dist/number/enum/uint8.d.mts.map +1 -1
  120. package/dist/number/enum/uint8.mjs +19 -14
  121. package/dist/number/enum/uint8.mjs.map +1 -1
  122. package/dist/number/refined-number-utils.d.mts +9 -9
  123. package/dist/number/refined-number-utils.d.mts.map +1 -1
  124. package/dist/number/refined-number-utils.mjs +7 -7
  125. package/dist/number/refined-number-utils.mjs.map +1 -1
  126. package/package.json +1 -1
  127. package/src/number/branded-types/int16.mts +13 -8
  128. package/src/number/branded-types/int32.mts +13 -8
  129. package/src/number/branded-types/negative-finite-number.mts +15 -8
  130. package/src/number/branded-types/negative-finite-number.test.mts +4 -4
  131. package/src/number/branded-types/negative-int.mts +13 -8
  132. package/src/number/branded-types/negative-int.test.mts +5 -5
  133. package/src/number/branded-types/negative-safe-int.mts +15 -9
  134. package/src/number/branded-types/negative-safe-int.test.mts +4 -4
  135. package/src/number/branded-types/non-negative-finite-number.mts +12 -7
  136. package/src/number/branded-types/non-negative-int16.mts +14 -8
  137. package/src/number/branded-types/non-negative-int32.mts +14 -8
  138. package/src/number/branded-types/non-positive-finite-number.mts +12 -7
  139. package/src/number/branded-types/non-positive-finite-number.test.mts +7 -7
  140. package/src/number/branded-types/non-positive-int.mts +12 -7
  141. package/src/number/branded-types/non-positive-int.test.mts +7 -7
  142. package/src/number/branded-types/non-positive-safe-int.mts +15 -8
  143. package/src/number/branded-types/non-positive-safe-int.test.mts +7 -7
  144. package/src/number/branded-types/non-zero-int16.mts +14 -8
  145. package/src/number/branded-types/non-zero-int32.mts +14 -8
  146. package/src/number/branded-types/non-zero-safe-int.mts +14 -8
  147. package/src/number/branded-types/non-zero-uint16.mts +14 -8
  148. package/src/number/branded-types/non-zero-uint32.mts +14 -8
  149. package/src/number/branded-types/positive-finite-number.mts +14 -7
  150. package/src/number/branded-types/positive-int.mts +14 -9
  151. package/src/number/branded-types/positive-int16.mts +14 -8
  152. package/src/number/branded-types/positive-int32.mts +14 -8
  153. package/src/number/branded-types/positive-safe-int.mts +17 -11
  154. package/src/number/branded-types/positive-uint16.mts +14 -8
  155. package/src/number/branded-types/positive-uint32.mts +14 -8
  156. package/src/number/branded-types/safe-int.mts +16 -11
  157. package/src/number/branded-types/safe-uint.mts +13 -8
  158. package/src/number/branded-types/uint.mts +15 -11
  159. package/src/number/branded-types/uint16.mts +13 -8
  160. package/src/number/branded-types/uint32.mts +13 -8
  161. package/src/number/enum/int8.mts +20 -14
  162. package/src/number/enum/int8.test.mts +7 -4
  163. package/src/number/enum/uint8.mts +20 -14
  164. package/src/number/enum/uint8.test.mts +7 -4
  165. package/src/number/refined-number-utils.mts +22 -19
@@ -23,12 +23,12 @@ var TsDataForgeInternals;
23
23
  }) => {
24
24
  const is = (a) => (integerOrSafeInteger === "Integer" ? Number.isInteger(a) : Number.isSafeInteger(a)) && (nonZero === true ? a !== 0 : true) && (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);
25
25
  const castType = castTypeImpl(is, typeNameInMessage);
26
- const clamp = pipe(
26
+ const fromNumber = pipe(
27
27
  clampFnOrUndefined(MIN_VALUE, MAX_VALUE)
28
28
  ).mapNullable(
29
29
  (cl) => (x) => castType(Math.round(cl(x)))
30
30
  ).value;
31
- const clampOrCastFn = clamp ?? castType;
31
+ const clampOrCastFn = fromNumber ?? castType;
32
32
  const abs = (x) => (
33
33
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
34
34
  Math.abs(clampOrCastFn(x))
@@ -68,9 +68,9 @@ var TsDataForgeInternals;
68
68
  random,
69
69
  randomNonZero,
70
70
  castType,
71
- clamp: (
71
+ fromNumber: (
72
72
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
73
- clamp
73
+ fromNumber
74
74
  )
75
75
  };
76
76
  };
@@ -82,12 +82,12 @@ var TsDataForgeInternals;
82
82
  }) => {
83
83
  const is = (a) => Number.isFinite(a) && (nonZero === true ? a !== 0 : true) && (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);
84
84
  const castType = castTypeImpl(is, typeNameInMessage);
85
- const clamp = pipe(
85
+ const fromNumber = pipe(
86
86
  clampFnOrUndefined(MIN_VALUE, MAX_VALUE)
87
87
  ).mapNullable(
88
88
  (cl) => (x) => castType(cl(x))
89
89
  ).value;
90
- const clampOrCastFn = clamp ?? castType;
90
+ const clampOrCastFn = fromNumber ?? castType;
91
91
  const abs = (x) => (
92
92
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
93
93
  Math.abs(x)
@@ -126,7 +126,7 @@ var TsDataForgeInternals;
126
126
  randomNonZero,
127
127
  castType,
128
128
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
129
- clamp
129
+ fromNumber
130
130
  };
131
131
  };
132
132
  })(TsDataForgeInternals2.RefinedNumberUtils || (TsDataForgeInternals2.RefinedNumberUtils = {}));
@@ -1 +1 @@
1
- {"version":3,"file":"refined-number-utils.mjs","sources":["../../src/number/refined-number-utils.mts"],"sourcesContent":["import {\n type Brand,\n type ChangeBaseBrand,\n type GetBrandValuePart,\n type Int,\n type IntersectBrand,\n type NonNegativeNumber,\n type NonZeroNumber,\n type PositiveNumber,\n type RelaxedExclude,\n type TypeEq,\n type UnknownBrand,\n type UnwrapBrandFalseKeys,\n type UnwrapBrandTrueKeys,\n type WithSmallInt,\n} from 'ts-type-forge';\nimport { expectType } from '../expect-type.mjs';\nimport { pipe } from '../functional/index.mjs';\nimport { Num } from './num.mjs';\n\n/** @internal */\nexport namespace TsDataForgeInternals {\n /**\n * Internal utilities for creating and managing refined (branded) number\n * types.\n *\n * This namespace provides factory functions and type utilities for building\n * type-safe numeric operations with compile-time constraints. It serves as\n * the foundation for all branded number types in the library, including:\n *\n * - Integer types (Int, SafeInt, Int8, Int16, Int32)\n * - Unsigned types (UInt, UInt8, UInt16, UInt32)\n * - Constrained types (NonZero, NonNegative, Positive)\n * - Range-bounded types\n *\n * The utilities handle:\n *\n * - Type validation and narrowing\n * - Arithmetic operations that preserve type constraints\n * - Automatic clamping for bounded types\n * - Random number generation within type bounds\n *\n * @internal This namespace is not part of the public API\n */\n export namespace RefinedNumberUtils {\n const castTypeImpl =\n <BrandedType extends number>(\n is: (n: number) => n is BrandedType,\n typeNameInErrorMessage: string,\n ) =>\n <N extends number>(a: N): BrandedType & N => {\n if (!is(a)) {\n throw new TypeError(`Expected ${typeNameInErrorMessage}, got: ${a}`);\n }\n\n return a;\n };\n\n type UnknownNumberBrand = ChangeBaseBrand<UnknownBrand, number>;\n\n /**\n * Converts a branded number type to include the Int brand.\n *\n * @template N - A branded number type\n * @internal\n */\n export type ToInt<N extends UnknownNumberBrand> = IntersectBrand<N, Int>;\n\n type ToNonZero<N extends UnknownNumberBrand> = IntersectBrand<\n N,\n NonZeroNumber\n >;\n\n const isNonZero = <N extends UnknownNumberBrand>(\n n: N,\n ): n is N & ToNonZero<N> => n !== 0;\n\n type ToNonZeroIntWithSmallInt<N extends Int> = WithSmallInt<\n CastToInt<ToNonZero<N>>\n >;\n\n /**\n * Converts a branded number type to include the NonNegativeNumber brand.\n *\n * @template N - A branded number type\n * @internal\n */\n export type ToNonNegative<N extends UnknownNumberBrand> =\n '!=0' extends UnwrapBrandTrueKeys<N>\n ? IntersectBrand<N, PositiveNumber>\n : IntersectBrand<N, NonNegativeNumber>;\n\n /**\n * Removes the non-zero brand constraint from a branded number type. Used\n * when operations may produce zero values.\n *\n * @template N - A branded number type\n * @internal\n */\n export type RemoveNonZeroBrandKey<N extends UnknownNumberBrand> = Brand<\n GetBrandValuePart<N>,\n RelaxedExclude<UnwrapBrandTrueKeys<N>, '!=0'> & string,\n RelaxedExclude<UnwrapBrandFalseKeys<N>, '<=0' | '>=0'> & string\n >;\n\n type CastToInt<N> = N extends Int ? N : never;\n\n /**\n * Generates a type-safe API for a branded number type based on its\n * characteristics.\n *\n * This type dynamically constructs an object type with appropriate methods\n * based on the number class. For example:\n *\n * - Integer types don't get floor/ceil/round methods\n * - Non-negative types don't get abs method\n * - Range-bounded types get MIN_VALUE/MAX_VALUE constants\n *\n * @template N - The branded number type\n * @template classes - Union of characteristics: 'int' | 'non-negative' |\n * 'positive' | 'range'\n * @internal\n */\n /** The closed binary arithmetic operations a branded namespace may expose. */\n export type NumberClassBinOp = 'add' | 'div' | 'mul' | 'sub';\n\n export type NumberClass<\n N extends UnknownNumberBrand,\n classes extends 'int' | 'non-negative' | 'positive' | 'range',\n binOps extends NumberClassBinOp = NumberClassBinOp,\n > = ('int' extends classes\n ? unknown\n : 'positive' extends classes\n ? Readonly<{\n floor: (x: N, y: N) => RemoveNonZeroBrandKey<ToInt<N>>;\n ceil: (x: N, y: N) => ToInt<N>;\n round: (x: N, y: N) => RemoveNonZeroBrandKey<ToInt<N>>;\n }>\n : Readonly<{\n floor: (x: N, y: N) => ToInt<N>;\n ceil: (x: N, y: N) => ToInt<N>;\n round: (x: N, y: N) => ToInt<N>;\n }>) &\n ('non-negative' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n clamp: (a: number) => N;\n }>\n : unknown) &\n ('non-negative' extends classes\n ? unknown\n : 'positive' extends classes\n ? unknown\n : Readonly<{\n abs: (x: N) => ToNonNegative<N>;\n }>) &\n ('positive' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n clamp: (a: number) => N;\n }>\n : unknown) &\n ('range' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n MAX_VALUE: number;\n clamp: (a: number) => N;\n }>\n : unknown) &\n Pick<\n Readonly<{\n add: (x: N, y: N) => N;\n sub: (x: N, y: N) => N;\n mul: (x: N, y: N) => N;\n div: (x: N, y: ToNonZero<N>) => N;\n }>,\n binOps\n > &\n Readonly<{\n is: (a: number) => a is N;\n min: (...values: readonly N[]) => N;\n max: (...values: readonly N[]) => N;\n random: (min: N, max: N) => N;\n pow: (x: N, y: N) => N;\n }>;\n\n type BaseKeys =\n 'add' | 'div' | 'is' | 'max' | 'min' | 'mul' | 'pow' | 'random' | 'sub';\n\n type FloatMethods = 'ceil' | 'floor' | 'round';\n\n expectType<keyof NumberClass<UnknownNumberBrand, 'int'>, BaseKeys | 'abs'>(\n '=',\n );\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, never>,\n BaseKeys | FloatMethods | 'abs'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'non-negative'>,\n BaseKeys | FloatMethods | 'clamp' | 'MIN_VALUE'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'positive'>,\n BaseKeys | FloatMethods | 'clamp' | 'MIN_VALUE'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'int' | 'range'>,\n BaseKeys | 'abs' | 'clamp' | 'MAX_VALUE' | 'MIN_VALUE'\n >('=');\n\n const isFnOrUndefined = (\n min: number | undefined,\n max: number | undefined,\n ): ((n: number) => boolean) | undefined =>\n min === undefined\n ? max === undefined\n ? undefined\n : (n) => n <= max\n : max === undefined\n ? (n) => min <= n\n : Num.isInRangeInclusive(min, max);\n\n const clampFnOrUndefined = (\n min: number | undefined,\n max: number | undefined,\n ): ((n: number) => number) | undefined =>\n min === undefined\n ? max === undefined\n ? undefined\n : (n) => Math.min(max, n)\n : max === undefined\n ? (n) => Math.max(min, n)\n : Num.clamp(min, max);\n\n type OperatorsForInteger<\n ElementType extends Int,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n ElementTypeWithSmallInt extends WithSmallInt<ElementType> =\n WithSmallInt<ElementType>,\n > = Readonly<{\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n\n is: (a: number) => a is ElementType;\n\n abs: (x: ElementTypeWithSmallInt) => ToNonNegative<ElementType>;\n\n min: (...values: readonly ElementTypeWithSmallInt[]) => ElementType;\n\n max: (...values: readonly ElementTypeWithSmallInt[]) => ElementType;\n\n pow: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n add: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n sub: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n mul: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n div: (\n x: ElementTypeWithSmallInt,\n y: ToNonZeroIntWithSmallInt<ElementType>,\n ) => ElementType;\n\n random: (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ) => ElementType;\n\n randomNonZero: (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ) => ElementType;\n\n castType: <N extends number>(x: N) => ElementType & N;\n\n clamp: TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType;\n }>;\n\n /**\n * Factory function that creates a complete set of type-safe operations for\n * integer types.\n *\n * This function generates:\n *\n * - Type guards and validators\n * - Arithmetic operations that preserve type constraints\n * - Utility functions (min, max, abs, random)\n * - Automatic clamping for bounded types\n *\n * All operations ensure results remain within the type's constraints, using\n * clamping when bounds are specified.\n *\n * @example\n *\n * ```ts\n * const intOps = TsDataForgeInternals.RefinedNumberUtils.operatorsForInteger<\n * SafeInt,\n * number,\n * number\n * >({\n * integerOrSafeInteger: 'SafeInteger',\n * MIN_VALUE: Number.MIN_SAFE_INTEGER,\n * MAX_VALUE: Number.MAX_SAFE_INTEGER,\n * typeNameInMessage: 'SafeInt',\n * } as const);\n *\n * const six = intOps.castType(6);\n *\n * const four = intOps.castType(4);\n *\n * const sum = intOps.add(six, four);\n *\n * const difference = intOps.sub(six, four);\n *\n * const product = intOps.mul(six, four);\n *\n * const quotient = intOps.div(six, intOps.castType(2));\n *\n * const roundedClamp = intOps.clamp(1.5);\n *\n * const randomValue = intOps.random();\n *\n * assert.isTrue(sum === 10);\n *\n * assert.isTrue(difference === 2);\n *\n * assert.isTrue(product === 24);\n *\n * assert.isTrue(quotient === 3);\n *\n * assert.isTrue(roundedClamp === 2);\n *\n * assert.isTrue(Number.isSafeInteger(randomValue));\n * ```\n *\n * @template ElementType - The integer branded type\n * @template MIN_VALUE - Optional minimum value for bounded types\n * @template MAX_VALUE - Optional maximum value for bounded types\n * @param config - Configuration object\n * @param config.integerOrSafeInteger - Whether to use Number.isInteger or\n * Number.isSafeInteger\n * @param config.nonZero - If true, excludes zero from valid values\n * @param config.MIN_VALUE - Minimum valid value (inclusive)\n * @param config.MAX_VALUE - Maximum valid value (inclusive)\n * @param config.typeNameInMessage - Human-readable type name for error\n * messages\n * @returns Object containing all type-safe operations for the integer type\n * @internal\n */\n export const operatorsForInteger = <\n ElementType extends Int,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n >({\n integerOrSafeInteger,\n nonZero,\n MIN_VALUE,\n MAX_VALUE,\n typeNameInMessage,\n }: Readonly<{\n integerOrSafeInteger: 'Integer' | 'SafeInteger';\n nonZero?: boolean;\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n typeNameInMessage: string;\n }>): OperatorsForInteger<ElementType, MIN_VALUE, MAX_VALUE> => {\n type ElementTypeWithSmallInt = WithSmallInt<ElementType>;\n\n const is = (a: number): a is ElementType =>\n (integerOrSafeInteger === 'Integer'\n ? Number.isInteger(a)\n : Number.isSafeInteger(a)) &&\n (nonZero === true ? a !== 0 : true) &&\n (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);\n\n const castType = castTypeImpl<ElementType>(is, typeNameInMessage);\n\n const clamp: ((a: number) => ElementType) | undefined = pipe(\n clampFnOrUndefined(MIN_VALUE, MAX_VALUE),\n ).mapNullable(\n (cl) =>\n (x: number): ElementType =>\n castType(Math.round(cl(x))),\n ).value;\n\n const clampOrCastFn: (a: number) => ElementType = clamp ?? castType;\n\n const abs = (x: ElementTypeWithSmallInt): ToNonNegative<ElementType> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Math.abs(clampOrCastFn(x)) as ToNonNegative<ElementType>;\n\n const min_ = (\n ...values: readonly ElementTypeWithSmallInt[]\n ): ElementType => clampOrCastFn(Math.min(...values));\n\n const max_ = (\n ...values: readonly ElementTypeWithSmallInt[]\n ): ElementType => clampOrCastFn(Math.max(...values));\n\n const pow = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x ** y);\n\n const add = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x + y);\n\n const sub = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x - y);\n\n const mul = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x * y);\n\n const div = (\n x: ElementTypeWithSmallInt,\n y: ToNonZeroIntWithSmallInt<ElementType>,\n ): ElementType =>\n clampOrCastFn(\n Math.floor(\n // eslint-disable-next-line total-functions/no-partial-division\n x / y,\n ),\n );\n\n const randomImpl = (\n min: number = MIN_VALUE,\n max: number = MAX_VALUE,\n ): number =>\n min + Math.floor((Math.max(max, min) - min + 1) * Math.random());\n\n // [-5, 5] -> floor(11 * Math.random()) + (-5)\n const random = (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(randomImpl(min, max));\n\n const randomNonZero = (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ): ElementType => {\n while (true) {\n const r = randomImpl(min, max);\n\n if (Num.isNonZero(r)) return clampOrCastFn(r);\n }\n };\n\n return {\n MIN_VALUE,\n MAX_VALUE,\n is,\n abs,\n min: min_,\n max: max_,\n pow,\n add,\n sub,\n mul,\n div,\n random,\n randomNonZero,\n castType,\n\n clamp:\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n clamp as TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType,\n } as const;\n };\n\n type OperatorsForFloat<\n ElementType extends UnknownNumberBrand,\n MIN_VALUE extends number | undefined,\n MAX_VALUE extends number | undefined,\n > = Readonly<{\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n\n is: (a: number) => a is ElementType;\n\n abs: (x: ElementType) => ToNonNegative<ElementType>;\n min: (...values: readonly ElementType[]) => ElementType;\n max: (...values: readonly ElementType[]) => ElementType;\n pow: (x: ElementType, y: ElementType) => ElementType;\n add: (x: ElementType, y: ElementType) => ElementType;\n sub: (x: ElementType, y: ElementType) => ElementType;\n mul: (x: ElementType, y: ElementType) => ElementType;\n div: (x: ElementType, y: ToNonZero<ElementType>) => ElementType;\n random: (min?: ElementType, max?: ElementType) => ElementType;\n randomNonZero: (min?: ElementType, max?: ElementType) => ElementType;\n\n castType: <N extends number>(x: N) => ElementType & N;\n\n clamp: TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType;\n }>;\n\n /**\n * Factory function that creates a complete set of type-safe operations for\n * floating-point types.\n *\n * This function generates:\n *\n * - Type guards and validators (checking for finite values)\n * - Arithmetic operations that preserve type constraints\n * - Utility functions (min, max, abs, random)\n * - Automatic clamping for bounded types\n *\n * All operations ensure results remain finite and within any specified\n * bounds. Division by zero is prevented through type constraints.\n *\n * @example\n *\n * ```ts\n * const floatOps = TsDataForgeInternals.RefinedNumberUtils.operatorsForFloat<\n * PositiveFiniteNumber,\n * number,\n * number\n * >({\n * nonZero: true,\n * MIN_VALUE: Number.MIN_VALUE,\n * MAX_VALUE: Number.MAX_VALUE,\n * typeNameInMessage: 'PositiveFiniteNumber',\n * } as const);\n *\n * const fortyTwo = floatOps.castType(42.5);\n *\n * const seven = floatOps.castType(7.5);\n *\n * const sum = floatOps.add(fortyTwo, seven);\n *\n * const ratio = floatOps.div(sum, floatOps.castType(10));\n *\n * const clamped = floatOps.clamp(0);\n *\n * const boundedRandom = floatOps.random(\n * floatOps.castType(10),\n * floatOps.castType(20),\n * );\n *\n * const nonZeroRandom = floatOps.randomNonZero();\n *\n * assert.isTrue(sum === 50);\n *\n * assert.isTrue(ratio === 5);\n *\n * assert.isTrue(clamped >= Number.MIN_VALUE);\n *\n * assert.isTrue(boundedRandom >= 10 && boundedRandom <= 20);\n *\n * assert.isTrue(nonZeroRandom > 0);\n * ```\n *\n * @template ElementType - The floating-point branded type\n * @template MIN_VALUE - Optional minimum value for bounded types\n * @template MAX_VALUE - Optional maximum value for bounded types\n * @param config - Configuration object\n * @param config.nonZero - If true, excludes zero from valid values\n * @param config.MIN_VALUE - Minimum valid value (inclusive)\n * @param config.MAX_VALUE - Maximum valid value (inclusive)\n * @param config.typeNameInMessage - Human-readable type name for error\n * messages\n * @returns Object containing all type-safe operations for the\n * floating-point type\n * @internal\n */\n export const operatorsForFloat = <\n ElementType extends UnknownNumberBrand,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n >({\n nonZero,\n MIN_VALUE,\n MAX_VALUE,\n typeNameInMessage,\n }: Readonly<{\n nonZero?: boolean;\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n typeNameInMessage: string;\n }>): OperatorsForFloat<ElementType, MIN_VALUE, MAX_VALUE> => {\n const is = (a: number): a is ElementType =>\n Number.isFinite(a) &&\n (nonZero === true ? a !== 0 : true) &&\n (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);\n\n const castType = castTypeImpl<ElementType>(is, typeNameInMessage);\n\n const clamp: ((a: number) => ElementType) | undefined = pipe(\n clampFnOrUndefined(MIN_VALUE, MAX_VALUE),\n ).mapNullable(\n (cl) =>\n (x: number): ElementType =>\n castType(cl(x)),\n ).value;\n\n const clampOrCastFn: (a: number) => ElementType = clamp ?? castType;\n\n const abs = (x: ElementType): ToNonNegative<ElementType> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Math.abs(x) as ToNonNegative<ElementType>;\n\n const min_ = (...values: readonly ElementType[]): ElementType =>\n clampOrCastFn(Math.min(...values));\n\n const max_ = (...values: readonly ElementType[]): ElementType =>\n clampOrCastFn(Math.max(...values));\n\n const pow = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x ** y);\n\n const add = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x + y);\n\n const sub = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x - y);\n\n const mul = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x * y);\n\n const div = (x: ElementType, y: ToNonZero<ElementType>): ElementType =>\n // eslint-disable-next-line total-functions/no-partial-division\n clampOrCastFn(x / y);\n\n const randomImpl = (\n min: number = MIN_VALUE,\n max: number = MAX_VALUE,\n ): number => min + (Math.max(max, min) - min) * Math.random();\n\n const random = (min?: ElementType, max?: ElementType): ElementType =>\n clampOrCastFn(randomImpl(min, max));\n\n const randomNonZero = (\n min?: ElementType,\n max?: ElementType,\n ): ElementType => {\n while (true) {\n const r = random(min, max);\n\n if (isNonZero(r)) return r;\n }\n };\n\n return {\n MIN_VALUE,\n MAX_VALUE,\n is,\n abs,\n min: min_,\n max: max_,\n pow,\n add,\n sub,\n mul,\n div,\n random,\n randomNonZero,\n castType,\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n clamp: clamp as TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType,\n } as const;\n };\n }\n}\n"],"names":["TsDataForgeInternals","RefinedNumberUtils"],"mappings":"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"}
1
+ {"version":3,"file":"refined-number-utils.mjs","sources":["../../src/number/refined-number-utils.mts"],"sourcesContent":["import {\n type Brand,\n type ChangeBaseBrand,\n type GetBrandValuePart,\n type Int,\n type IntersectBrand,\n type NonNegativeNumber,\n type NonZeroNumber,\n type PositiveNumber,\n type RelaxedExclude,\n type TypeEq,\n type UnknownBrand,\n type UnwrapBrandFalseKeys,\n type UnwrapBrandTrueKeys,\n type WithSmallInt,\n} from 'ts-type-forge';\nimport { expectType } from '../expect-type.mjs';\nimport { pipe } from '../functional/index.mjs';\nimport { Num } from './num.mjs';\n\n/** @internal */\nexport namespace TsDataForgeInternals {\n /**\n * Internal utilities for creating and managing refined (branded) number\n * types.\n *\n * This namespace provides factory functions and type utilities for building\n * type-safe numeric operations with compile-time constraints. It serves as\n * the foundation for all branded number types in the library, including:\n *\n * - Integer types (Int, SafeInt, Int8, Int16, Int32)\n * - Unsigned types (UInt, UInt8, UInt16, UInt32)\n * - Constrained types (NonZero, NonNegative, Positive)\n * - Range-bounded types\n *\n * The utilities handle:\n *\n * - Type validation and narrowing\n * - Arithmetic operations that preserve type constraints\n * - Automatic clamping for bounded types\n * - Random number generation within type bounds\n *\n * @internal This namespace is not part of the public API\n */\n export namespace RefinedNumberUtils {\n const castTypeImpl =\n <BrandedType extends number>(\n is: (n: number) => n is BrandedType,\n typeNameInErrorMessage: string,\n ) =>\n <N extends number>(a: N): BrandedType & N => {\n if (!is(a)) {\n throw new TypeError(`Expected ${typeNameInErrorMessage}, got: ${a}`);\n }\n\n return a;\n };\n\n type UnknownNumberBrand = ChangeBaseBrand<UnknownBrand, number>;\n\n /**\n * Converts a branded number type to include the Int brand.\n *\n * @template N - A branded number type\n * @internal\n */\n export type ToInt<N extends UnknownNumberBrand> = IntersectBrand<N, Int>;\n\n type ToNonZero<N extends UnknownNumberBrand> = IntersectBrand<\n N,\n NonZeroNumber\n >;\n\n const isNonZero = <N extends UnknownNumberBrand>(\n n: N,\n ): n is N & ToNonZero<N> => n !== 0;\n\n type ToNonZeroIntWithSmallInt<N extends Int> = WithSmallInt<\n CastToInt<ToNonZero<N>>\n >;\n\n /**\n * Converts a branded number type to include the NonNegativeNumber brand.\n *\n * @template N - A branded number type\n * @internal\n */\n export type ToNonNegative<N extends UnknownNumberBrand> =\n '!=0' extends UnwrapBrandTrueKeys<N>\n ? IntersectBrand<N, PositiveNumber>\n : IntersectBrand<N, NonNegativeNumber>;\n\n /**\n * Removes the non-zero brand constraint from a branded number type. Used\n * when operations may produce zero values.\n *\n * @template N - A branded number type\n * @internal\n */\n export type RemoveNonZeroBrandKey<N extends UnknownNumberBrand> = Brand<\n GetBrandValuePart<N>,\n RelaxedExclude<UnwrapBrandTrueKeys<N>, '!=0'> & string,\n RelaxedExclude<UnwrapBrandFalseKeys<N>, '<=0' | '>=0'> & string\n >;\n\n type CastToInt<N> = N extends Int ? N : never;\n\n /**\n * Generates a type-safe API for a branded number type based on its\n * characteristics.\n *\n * This type dynamically constructs an object type with appropriate methods\n * based on the number class. For example:\n *\n * - Integer types don't get floor/ceil/round methods\n * - Non-negative types don't get abs method\n * - Range-bounded types get MIN_VALUE/MAX_VALUE constants\n *\n * @template N - The branded number type\n * @template classes - Union of characteristics: 'int' | 'non-negative' |\n * 'positive' | 'range'\n * @internal\n */\n /** The closed binary arithmetic operations a branded namespace may expose. */\n export type NumberClassBinOp = 'add' | 'div' | 'mul' | 'sub';\n\n export type NumberClass<\n N extends UnknownNumberBrand,\n classes extends 'int' | 'non-negative' | 'positive' | 'range',\n binOps extends NumberClassBinOp = NumberClassBinOp,\n > = ('int' extends classes\n ? unknown\n : 'positive' extends classes\n ? Readonly<{\n floor: (x: N, y: N) => RemoveNonZeroBrandKey<ToInt<N>>;\n ceil: (x: N, y: N) => ToInt<N>;\n round: (x: N, y: N) => RemoveNonZeroBrandKey<ToInt<N>>;\n }>\n : Readonly<{\n floor: (x: N, y: N) => ToInt<N>;\n ceil: (x: N, y: N) => ToInt<N>;\n round: (x: N, y: N) => ToInt<N>;\n }>) &\n ('non-negative' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n fromNumber: (a: number) => N;\n }>\n : unknown) &\n ('non-negative' extends classes\n ? unknown\n : 'positive' extends classes\n ? unknown\n : Readonly<{\n abs: (x: N) => ToNonNegative<N>;\n }>) &\n ('positive' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n fromNumber: (a: number) => N;\n }>\n : unknown) &\n ('range' extends classes\n ? Readonly<{\n MIN_VALUE: number;\n MAX_VALUE: number;\n fromNumber: (a: number) => N;\n }>\n : unknown) &\n Pick<\n Readonly<{\n add: (x: N, y: N) => N;\n sub: (x: N, y: N) => N;\n mul: (x: N, y: N) => N;\n div: (x: N, y: ToNonZero<N>) => N;\n }>,\n binOps\n > &\n Readonly<{\n is: (a: number) => a is N;\n min: (...values: readonly N[]) => N;\n max: (...values: readonly N[]) => N;\n random: (min: N, max: N) => N;\n pow: (x: N, y: N) => N;\n }>;\n\n type BaseKeys =\n 'add' | 'div' | 'is' | 'max' | 'min' | 'mul' | 'pow' | 'random' | 'sub';\n\n type FloatMethods = 'ceil' | 'floor' | 'round';\n\n expectType<keyof NumberClass<UnknownNumberBrand, 'int'>, BaseKeys | 'abs'>(\n '=',\n );\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, never>,\n BaseKeys | FloatMethods | 'abs'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'non-negative'>,\n BaseKeys | FloatMethods | 'fromNumber' | 'MIN_VALUE'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'positive'>,\n BaseKeys | FloatMethods | 'fromNumber' | 'MIN_VALUE'\n >('=');\n\n expectType<\n keyof NumberClass<UnknownNumberBrand, 'int' | 'range'>,\n BaseKeys | 'abs' | 'fromNumber' | 'MAX_VALUE' | 'MIN_VALUE'\n >('=');\n\n const isFnOrUndefined = (\n min: number | undefined,\n max: number | undefined,\n ): ((n: number) => boolean) | undefined =>\n min === undefined\n ? max === undefined\n ? undefined\n : (n) => n <= max\n : max === undefined\n ? (n) => min <= n\n : Num.isInRangeInclusive(min, max);\n\n const clampFnOrUndefined = (\n min: number | undefined,\n max: number | undefined,\n ): ((n: number) => number) | undefined =>\n min === undefined\n ? max === undefined\n ? undefined\n : (n) => Math.min(max, n)\n : max === undefined\n ? (n) => Math.max(min, n)\n : Num.clamp(min, max);\n\n type OperatorsForInteger<\n ElementType extends Int,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n ElementTypeWithSmallInt extends WithSmallInt<ElementType> =\n WithSmallInt<ElementType>,\n > = Readonly<{\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n\n is: (a: number) => a is ElementType;\n\n abs: (x: ElementTypeWithSmallInt) => ToNonNegative<ElementType>;\n\n min: (...values: readonly ElementTypeWithSmallInt[]) => ElementType;\n\n max: (...values: readonly ElementTypeWithSmallInt[]) => ElementType;\n\n pow: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n add: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n sub: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n mul: (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ) => ElementType;\n\n div: (\n x: ElementTypeWithSmallInt,\n y: ToNonZeroIntWithSmallInt<ElementType>,\n ) => ElementType;\n\n random: (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ) => ElementType;\n\n randomNonZero: (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ) => ElementType;\n\n castType: <N extends number>(x: N) => ElementType & N;\n\n fromNumber: TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType;\n }>;\n\n /**\n * Factory function that creates a complete set of type-safe operations for\n * integer types.\n *\n * This function generates:\n *\n * - Type guards and validators\n * - Arithmetic operations that preserve type constraints\n * - Utility functions (min, max, abs, random)\n * - Automatic clamping for bounded types\n *\n * All operations ensure results remain within the type's constraints, using\n * clamping when bounds are specified.\n *\n * @example\n *\n * ```ts\n * const intOps = TsDataForgeInternals.RefinedNumberUtils.operatorsForInteger<\n * SafeInt,\n * number,\n * number\n * >({\n * integerOrSafeInteger: 'SafeInteger',\n * MIN_VALUE: Number.MIN_SAFE_INTEGER,\n * MAX_VALUE: Number.MAX_SAFE_INTEGER,\n * typeNameInMessage: 'SafeInt',\n * } as const);\n *\n * const six = intOps.castType(6);\n *\n * const four = intOps.castType(4);\n *\n * const sum = intOps.add(six, four);\n *\n * const difference = intOps.sub(six, four);\n *\n * const product = intOps.mul(six, four);\n *\n * const quotient = intOps.div(six, intOps.castType(2));\n *\n * const coerced = intOps.fromNumber(1.5);\n *\n * const randomValue = intOps.random();\n *\n * assert.isTrue(sum === 10);\n *\n * assert.isTrue(difference === 2);\n *\n * assert.isTrue(product === 24);\n *\n * assert.isTrue(quotient === 3);\n *\n * assert.isTrue(coerced === 2);\n *\n * assert.isTrue(Number.isSafeInteger(randomValue));\n * ```\n *\n * @template ElementType - The integer branded type\n * @template MIN_VALUE - Optional minimum value for bounded types\n * @template MAX_VALUE - Optional maximum value for bounded types\n * @param config - Configuration object\n * @param config.integerOrSafeInteger - Whether to use Number.isInteger or\n * Number.isSafeInteger\n * @param config.nonZero - If true, excludes zero from valid values\n * @param config.MIN_VALUE - Minimum valid value (inclusive)\n * @param config.MAX_VALUE - Maximum valid value (inclusive)\n * @param config.typeNameInMessage - Human-readable type name for error\n * messages\n * @returns Object containing all type-safe operations for the integer type\n * @internal\n */\n export const operatorsForInteger = <\n ElementType extends Int,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n >({\n integerOrSafeInteger,\n nonZero,\n MIN_VALUE,\n MAX_VALUE,\n typeNameInMessage,\n }: Readonly<{\n integerOrSafeInteger: 'Integer' | 'SafeInteger';\n nonZero?: boolean;\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n typeNameInMessage: string;\n }>): OperatorsForInteger<ElementType, MIN_VALUE, MAX_VALUE> => {\n type ElementTypeWithSmallInt = WithSmallInt<ElementType>;\n\n const is = (a: number): a is ElementType =>\n (integerOrSafeInteger === 'Integer'\n ? Number.isInteger(a)\n : Number.isSafeInteger(a)) &&\n (nonZero === true ? a !== 0 : true) &&\n (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);\n\n const castType = castTypeImpl<ElementType>(is, typeNameInMessage);\n\n const fromNumber: ((a: number) => ElementType) | undefined = pipe(\n clampFnOrUndefined(MIN_VALUE, MAX_VALUE),\n ).mapNullable(\n (cl) =>\n (x: number): ElementType =>\n castType(Math.round(cl(x))),\n ).value;\n\n const clampOrCastFn: (a: number) => ElementType = fromNumber ?? castType;\n\n const abs = (x: ElementTypeWithSmallInt): ToNonNegative<ElementType> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Math.abs(clampOrCastFn(x)) as ToNonNegative<ElementType>;\n\n const min_ = (\n ...values: readonly ElementTypeWithSmallInt[]\n ): ElementType => clampOrCastFn(Math.min(...values));\n\n const max_ = (\n ...values: readonly ElementTypeWithSmallInt[]\n ): ElementType => clampOrCastFn(Math.max(...values));\n\n const pow = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x ** y);\n\n const add = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x + y);\n\n const sub = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x - y);\n\n const mul = (\n x: ElementTypeWithSmallInt,\n y: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(x * y);\n\n const div = (\n x: ElementTypeWithSmallInt,\n y: ToNonZeroIntWithSmallInt<ElementType>,\n ): ElementType =>\n clampOrCastFn(\n Math.floor(\n // eslint-disable-next-line total-functions/no-partial-division\n x / y,\n ),\n );\n\n const randomImpl = (\n min: number = MIN_VALUE,\n max: number = MAX_VALUE,\n ): number =>\n min + Math.floor((Math.max(max, min) - min + 1) * Math.random());\n\n // [-5, 5] -> floor(11 * Math.random()) + (-5)\n const random = (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ): ElementType => clampOrCastFn(randomImpl(min, max));\n\n const randomNonZero = (\n min?: ElementTypeWithSmallInt,\n max?: ElementTypeWithSmallInt,\n ): ElementType => {\n while (true) {\n const r = randomImpl(min, max);\n\n if (Num.isNonZero(r)) return clampOrCastFn(r);\n }\n };\n\n return {\n MIN_VALUE,\n MAX_VALUE,\n is,\n abs,\n min: min_,\n max: max_,\n pow,\n add,\n sub,\n mul,\n div,\n random,\n randomNonZero,\n castType,\n\n fromNumber:\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n fromNumber as TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType,\n } as const;\n };\n\n type OperatorsForFloat<\n ElementType extends UnknownNumberBrand,\n MIN_VALUE extends number | undefined,\n MAX_VALUE extends number | undefined,\n > = Readonly<{\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n\n is: (a: number) => a is ElementType;\n\n abs: (x: ElementType) => ToNonNegative<ElementType>;\n min: (...values: readonly ElementType[]) => ElementType;\n max: (...values: readonly ElementType[]) => ElementType;\n pow: (x: ElementType, y: ElementType) => ElementType;\n add: (x: ElementType, y: ElementType) => ElementType;\n sub: (x: ElementType, y: ElementType) => ElementType;\n mul: (x: ElementType, y: ElementType) => ElementType;\n div: (x: ElementType, y: ToNonZero<ElementType>) => ElementType;\n random: (min?: ElementType, max?: ElementType) => ElementType;\n randomNonZero: (min?: ElementType, max?: ElementType) => ElementType;\n\n castType: <N extends number>(x: N) => ElementType & N;\n\n fromNumber: TypeEq<MAX_VALUE | MIN_VALUE, undefined> extends true\n ? undefined\n : (x: number) => ElementType;\n }>;\n\n /**\n * Factory function that creates a complete set of type-safe operations for\n * floating-point types.\n *\n * This function generates:\n *\n * - Type guards and validators (checking for finite values)\n * - Arithmetic operations that preserve type constraints\n * - Utility functions (min, max, abs, random)\n * - Automatic clamping for bounded types\n *\n * All operations ensure results remain finite and within any specified\n * bounds. Division by zero is prevented through type constraints.\n *\n * @example\n *\n * ```ts\n * const floatOps = TsDataForgeInternals.RefinedNumberUtils.operatorsForFloat<\n * PositiveFiniteNumber,\n * number,\n * number\n * >({\n * nonZero: true,\n * MIN_VALUE: Number.MIN_VALUE,\n * MAX_VALUE: Number.MAX_VALUE,\n * typeNameInMessage: 'PositiveFiniteNumber',\n * } as const);\n *\n * const fortyTwo = floatOps.castType(42.5);\n *\n * const seven = floatOps.castType(7.5);\n *\n * const sum = floatOps.add(fortyTwo, seven);\n *\n * const ratio = floatOps.div(sum, floatOps.castType(10));\n *\n * const coerced = floatOps.fromNumber(0);\n *\n * const boundedRandom = floatOps.random(\n * floatOps.castType(10),\n * floatOps.castType(20),\n * );\n *\n * const nonZeroRandom = floatOps.randomNonZero();\n *\n * assert.isTrue(sum === 50);\n *\n * assert.isTrue(ratio === 5);\n *\n * assert.isTrue(coerced >= Number.MIN_VALUE);\n *\n * assert.isTrue(boundedRandom >= 10 && boundedRandom <= 20);\n *\n * assert.isTrue(nonZeroRandom > 0);\n * ```\n *\n * @template ElementType - The floating-point branded type\n * @template MIN_VALUE - Optional minimum value for bounded types\n * @template MAX_VALUE - Optional maximum value for bounded types\n * @param config - Configuration object\n * @param config.nonZero - If true, excludes zero from valid values\n * @param config.MIN_VALUE - Minimum valid value (inclusive)\n * @param config.MAX_VALUE - Maximum valid value (inclusive)\n * @param config.typeNameInMessage - Human-readable type name for error\n * messages\n * @returns Object containing all type-safe operations for the\n * floating-point type\n * @internal\n */\n export const operatorsForFloat = <\n ElementType extends UnknownNumberBrand,\n MIN_VALUE extends number,\n MAX_VALUE extends number,\n >({\n nonZero,\n MIN_VALUE,\n MAX_VALUE,\n typeNameInMessage,\n }: Readonly<{\n nonZero?: boolean;\n MIN_VALUE: MIN_VALUE;\n MAX_VALUE: MAX_VALUE;\n typeNameInMessage: string;\n }>): OperatorsForFloat<ElementType, MIN_VALUE, MAX_VALUE> => {\n const is = (a: number): a is ElementType =>\n Number.isFinite(a) &&\n (nonZero === true ? a !== 0 : true) &&\n (isFnOrUndefined(MIN_VALUE, MAX_VALUE)?.(a) ?? true);\n\n const castType = castTypeImpl<ElementType>(is, typeNameInMessage);\n\n const fromNumber: ((a: number) => ElementType) | undefined = pipe(\n clampFnOrUndefined(MIN_VALUE, MAX_VALUE),\n ).mapNullable(\n (cl) =>\n (x: number): ElementType =>\n castType(cl(x)),\n ).value;\n\n const clampOrCastFn: (a: number) => ElementType = fromNumber ?? castType;\n\n const abs = (x: ElementType): ToNonNegative<ElementType> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n Math.abs(x) as ToNonNegative<ElementType>;\n\n const min_ = (...values: readonly ElementType[]): ElementType =>\n clampOrCastFn(Math.min(...values));\n\n const max_ = (...values: readonly ElementType[]): ElementType =>\n clampOrCastFn(Math.max(...values));\n\n const pow = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x ** y);\n\n const add = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x + y);\n\n const sub = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x - y);\n\n const mul = (x: ElementType, y: ElementType): ElementType =>\n clampOrCastFn(x * y);\n\n const div = (x: ElementType, y: ToNonZero<ElementType>): ElementType =>\n // eslint-disable-next-line total-functions/no-partial-division\n clampOrCastFn(x / y);\n\n const randomImpl = (\n min: number = MIN_VALUE,\n max: number = MAX_VALUE,\n ): number => min + (Math.max(max, min) - min) * Math.random();\n\n const random = (min?: ElementType, max?: ElementType): ElementType =>\n clampOrCastFn(randomImpl(min, max));\n\n const randomNonZero = (\n min?: ElementType,\n max?: ElementType,\n ): ElementType => {\n while (true) {\n const r = random(min, max);\n\n if (isNonZero(r)) return r;\n }\n };\n\n return {\n MIN_VALUE,\n MAX_VALUE,\n is,\n abs,\n min: min_,\n max: max_,\n pow,\n add,\n sub,\n mul,\n div,\n random,\n randomNonZero,\n castType,\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n fromNumber: fromNumber as TypeEq<\n MAX_VALUE | MIN_VALUE,\n undefined\n > extends true\n ? undefined\n : (x: number) => ElementType,\n } as const;\n };\n }\n}\n"],"names":["TsDataForgeInternals","RefinedNumberUtils"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-data-forge",
3
- "version": "11.0.1",
3
+ "version": "12.0.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript",
@@ -14,8 +14,8 @@ const {
14
14
  abs,
15
15
  add,
16
16
  castType,
17
- clamp,
18
17
  div,
18
+ fromNumber,
19
19
  is,
20
20
  max: max_,
21
21
  min: min_,
@@ -74,12 +74,14 @@ export const Int16 = {
74
74
  is,
75
75
 
76
76
  /**
77
- * The smallest value representable as `Int16`.
77
+ * The smallest value representable as `Int16` (the lower saturation target of
78
+ * `fromNumber`).
78
79
  */
79
80
  MIN_VALUE,
80
81
 
81
82
  /**
82
- * The largest value representable as `Int16`.
83
+ * The largest value representable as `Int16` (the upper saturation target of
84
+ * `fromNumber`).
83
85
  */
84
86
  MAX_VALUE,
85
87
 
@@ -110,13 +112,16 @@ export const Int16 = {
110
112
  max: max_,
111
113
 
112
114
  /**
113
- * Clamps a `number` into the `Int16` range, rounding to the nearest integer
114
- * and constraining the result to `[MIN_VALUE, MAX_VALUE]`.
115
+ * Converts an arbitrary `number` into an `Int16`, rounding to the nearest
116
+ * integer and saturating the result into the range `[MIN_VALUE, MAX_VALUE]`.
115
117
  *
116
- * @param value - The value to clamp
117
- * @returns The clamped value as an `Int16`
118
+ * Unlike `asInt16`, this is total: out-of-range inputs are clamped to the
119
+ * nearest representable `Int16` instead of throwing.
120
+ *
121
+ * @param value - The value to convert
122
+ * @returns The value as an `Int16`
118
123
  */
119
- clamp,
124
+ fromNumber,
120
125
 
121
126
  /**
122
127
  * Generates a random `Int16` within the given range.
@@ -14,8 +14,8 @@ const {
14
14
  abs,
15
15
  add,
16
16
  castType,
17
- clamp,
18
17
  div,
18
+ fromNumber,
19
19
  is,
20
20
  max: max_,
21
21
  min: min_,
@@ -74,12 +74,14 @@ export const Int32 = {
74
74
  is,
75
75
 
76
76
  /**
77
- * The smallest value representable as `Int32`.
77
+ * The smallest value representable as `Int32` (the lower saturation target of
78
+ * `fromNumber`).
78
79
  */
79
80
  MIN_VALUE,
80
81
 
81
82
  /**
82
- * The largest value representable as `Int32`.
83
+ * The largest value representable as `Int32` (the upper saturation target of
84
+ * `fromNumber`).
83
85
  */
84
86
  MAX_VALUE,
85
87
 
@@ -110,13 +112,16 @@ export const Int32 = {
110
112
  max: max_,
111
113
 
112
114
  /**
113
- * Clamps a `number` into the `Int32` range, rounding to the nearest integer
114
- * and constraining the result to `[MIN_VALUE, MAX_VALUE]`.
115
+ * Converts an arbitrary `number` into an `Int32`, rounding to the nearest
116
+ * integer and saturating the result into the range `[MIN_VALUE, MAX_VALUE]`.
115
117
  *
116
- * @param value - The value to clamp
117
- * @returns The clamped value as an `Int32`
118
+ * Unlike `asInt32`, this is total: out-of-range inputs are clamped to the
119
+ * nearest representable `Int32` instead of throwing.
120
+ *
121
+ * @param value - The value to convert
122
+ * @returns The value as an `Int32`
118
123
  */
119
- clamp,
124
+ fromNumber,
120
125
 
121
126
  /**
122
127
  * Generates a random `Int32` within the given range.
@@ -12,7 +12,7 @@ const {
12
12
  MAX_VALUE,
13
13
  add,
14
14
  castType,
15
- clamp,
15
+ fromNumber,
16
16
  is,
17
17
  max: max_,
18
18
  min: min_,
@@ -31,7 +31,7 @@ const {
31
31
  } as const);
32
32
 
33
33
  const abs = (x: ElementType): PositiveFiniteNumber =>
34
- PositiveFiniteNumber.clamp(Math.abs(x));
34
+ PositiveFiniteNumber.fromNumber(Math.abs(x));
35
35
 
36
36
  const floor = (
37
37
  x: ElementType,
@@ -101,7 +101,10 @@ export const NegativeFiniteNumber = {
101
101
  is,
102
102
 
103
103
  /**
104
- * The largest value representable as `NegativeFiniteNumber`.
104
+ * The largest value representable as `NegativeFiniteNumber` (the upper
105
+ * saturation target of `fromNumber`). The domain is open at `0` (excluded),
106
+ * so this is `-Number.MIN_VALUE` — the negative double closest to `0` —
107
+ * rather than `0`.
105
108
  */
106
109
  MAX_VALUE,
107
110
 
@@ -132,13 +135,17 @@ export const NegativeFiniteNumber = {
132
135
  max: max_,
133
136
 
134
137
  /**
135
- * Clamps a `number` into the `NegativeFiniteNumber` range `[MIN_VALUE,
136
- * MAX_VALUE]`.
138
+ * Converts an arbitrary `number` into a `NegativeFiniteNumber`, saturating it
139
+ * into the range `[MIN_VALUE, MAX_VALUE]`.
137
140
  *
138
- * @param value - The value to clamp
139
- * @returns The clamped value as a `NegativeFiniteNumber`
141
+ * Unlike `asNegativeFiniteNumber`, this is total: out-of-range inputs are
142
+ * clamped to the nearest representable `NegativeFiniteNumber` instead of
143
+ * throwing.
144
+ *
145
+ * @param value - The value to convert
146
+ * @returns The value as a `NegativeFiniteNumber`
140
147
  */
141
- clamp,
148
+ fromNumber,
142
149
 
143
150
  /**
144
151
  * Returns the greatest integer less than or equal to a negative finite
@@ -93,13 +93,13 @@ describe('NegativeFiniteNumber test', () => {
93
93
  });
94
94
  });
95
95
 
96
- describe('NegativeFiniteNumber.clamp', () => {
96
+ describe('NegativeFiniteNumber.fromNumber', () => {
97
97
  test('clamps non-negative values into range', () => {
98
- expect(NegativeFiniteNumber.clamp(-5.5)).toBeCloseTo(-5.5, 5);
98
+ expect(NegativeFiniteNumber.fromNumber(-5.5)).toBeCloseTo(-5.5, 5);
99
99
 
100
- expect(NegativeFiniteNumber.clamp(0)).toBeLessThan(0);
100
+ expect(NegativeFiniteNumber.fromNumber(0)).toBeLessThan(0);
101
101
 
102
- expect(NegativeFiniteNumber.clamp(5)).toBeLessThan(0);
102
+ expect(NegativeFiniteNumber.fromNumber(5)).toBeLessThan(0);
103
103
  });
104
104
  });
105
105
 
@@ -15,7 +15,7 @@ const {
15
15
  MAX_VALUE,
16
16
  add,
17
17
  castType,
18
- clamp,
18
+ fromNumber,
19
19
  is,
20
20
  max: max_,
21
21
  min: min_,
@@ -35,7 +35,7 @@ const {
35
35
  } as const);
36
36
 
37
37
  const abs = (x: WithSmallInt<ElementType>): PositiveInt =>
38
- PositiveInt.clamp(Math.abs(x));
38
+ PositiveInt.fromNumber(Math.abs(x));
39
39
 
40
40
  /**
41
41
  * Type guard that checks if a value is a negative integer.
@@ -81,7 +81,8 @@ export const NegativeInt = {
81
81
  is,
82
82
 
83
83
  /**
84
- * The largest value representable as `NegativeInt`.
84
+ * The largest value representable as `NegativeInt` (the upper saturation
85
+ * target of `fromNumber`).
85
86
  */
86
87
  MAX_VALUE,
87
88
 
@@ -114,13 +115,17 @@ export const NegativeInt = {
114
115
  max: max_,
115
116
 
116
117
  /**
117
- * Clamps a `number` into the `NegativeInt` range, rounding to the nearest
118
- * integer and constraining the result to `[MIN_VALUE, MAX_VALUE]`.
118
+ * Converts an arbitrary `number` into a `NegativeInt`, rounding to the
119
+ * nearest integer and saturating the result into the range `[MIN_VALUE,
120
+ * MAX_VALUE]`.
119
121
  *
120
- * @param value - The value to clamp
121
- * @returns The clamped value as a `NegativeInt`
122
+ * Unlike `asNegativeInt`, this is total: out-of-range inputs are clamped to
123
+ * the nearest representable `NegativeInt` instead of throwing.
124
+ *
125
+ * @param value - The value to convert
126
+ * @returns The value as a `NegativeInt`
122
127
  */
123
- clamp,
128
+ fromNumber,
124
129
 
125
130
  /**
126
131
  * Generates a random `NegativeInt` within the given range.
@@ -96,17 +96,17 @@ describe('NegativeInt test', () => {
96
96
  });
97
97
  });
98
98
 
99
- describe('NegativeInt.clamp', () => {
99
+ describe('NegativeInt.fromNumber', () => {
100
100
  test('returns the same value if within range', () => {
101
- expect(NegativeInt.clamp(-5)).toBe(-5);
101
+ expect(NegativeInt.fromNumber(-5)).toBe(-5);
102
102
 
103
- expect(NegativeInt.clamp(-1000)).toBe(-1000);
103
+ expect(NegativeInt.fromNumber(-1000)).toBe(-1000);
104
104
  });
105
105
 
106
106
  test('clamps non-negative values to MAX_VALUE (-1)', () => {
107
- expect(NegativeInt.clamp(0)).toBe(-1);
107
+ expect(NegativeInt.fromNumber(0)).toBe(-1);
108
108
 
109
- expect(NegativeInt.clamp(5)).toBe(-1);
109
+ expect(NegativeInt.fromNumber(5)).toBe(-1);
110
110
  });
111
111
  });
112
112
 
@@ -16,7 +16,7 @@ const {
16
16
  MIN_VALUE,
17
17
  add,
18
18
  castType,
19
- clamp,
19
+ fromNumber,
20
20
  is,
21
21
  max: max_,
22
22
  min: min_,
@@ -36,7 +36,7 @@ const {
36
36
  } as const);
37
37
 
38
38
  const abs = (x: WithSmallInt<ElementType>): PositiveSafeInt =>
39
- PositiveSafeInt.clamp(Math.abs(x));
39
+ PositiveSafeInt.fromNumber(Math.abs(x));
40
40
 
41
41
  /**
42
42
  * Type guard that checks if a value is a negative safe integer.
@@ -79,12 +79,14 @@ export const NegativeSafeInt = {
79
79
  is,
80
80
 
81
81
  /**
82
- * The smallest value representable as `NegativeSafeInt`.
82
+ * The smallest value representable as `NegativeSafeInt` (the lower saturation
83
+ * target of `fromNumber`).
83
84
  */
84
85
  MIN_VALUE,
85
86
 
86
87
  /**
87
- * The largest value representable as `NegativeSafeInt`.
88
+ * The largest value representable as `NegativeSafeInt` (the upper saturation
89
+ * target of `fromNumber`).
88
90
  */
89
91
  MAX_VALUE,
90
92
 
@@ -115,13 +117,17 @@ export const NegativeSafeInt = {
115
117
  max: max_,
116
118
 
117
119
  /**
118
- * Clamps a `number` into the `NegativeSafeInt` range, rounding to the nearest
119
- * integer and constraining the result to `[MIN_VALUE, MAX_VALUE]`.
120
+ * Converts an arbitrary `number` into a `NegativeSafeInt`, rounding to the
121
+ * nearest integer and saturating the result into the range `[MIN_VALUE,
122
+ * MAX_VALUE]`.
120
123
  *
121
- * @param value - The value to clamp
122
- * @returns The clamped value as a `NegativeSafeInt`
124
+ * Unlike `asNegativeSafeInt`, this is total: out-of-range inputs are clamped
125
+ * to the nearest representable `NegativeSafeInt` instead of throwing.
126
+ *
127
+ * @param value - The value to convert
128
+ * @returns The value as a `NegativeSafeInt`
123
129
  */
124
- clamp,
130
+ fromNumber,
125
131
 
126
132
  /**
127
133
  * Generates a random `NegativeSafeInt` within the given range.
@@ -86,13 +86,13 @@ describe('NegativeSafeInt test', () => {
86
86
  });
87
87
  });
88
88
 
89
- describe('NegativeSafeInt.clamp', () => {
89
+ describe('NegativeSafeInt.fromNumber', () => {
90
90
  test('clamps to the valid range', () => {
91
- expect(NegativeSafeInt.clamp(-5)).toBe(-5);
91
+ expect(NegativeSafeInt.fromNumber(-5)).toBe(-5);
92
92
 
93
- expect(NegativeSafeInt.clamp(0)).toBe(-1);
93
+ expect(NegativeSafeInt.fromNumber(0)).toBe(-1);
94
94
 
95
- expect(NegativeSafeInt.clamp(Number.MIN_SAFE_INTEGER - 100)).toBe(
95
+ expect(NegativeSafeInt.fromNumber(Number.MIN_SAFE_INTEGER - 100)).toBe(
96
96
  Number.MIN_SAFE_INTEGER,
97
97
  );
98
98
  });
@@ -15,8 +15,8 @@ const {
15
15
  MIN_VALUE,
16
16
  add,
17
17
  castType,
18
- clamp,
19
18
  div,
19
+ fromNumber,
20
20
  is,
21
21
  max: max_,
22
22
  min: min_,
@@ -96,7 +96,8 @@ export const NonNegativeFiniteNumber = {
96
96
  is,
97
97
 
98
98
  /**
99
- * The smallest value representable as `NonNegativeFiniteNumber`.
99
+ * The smallest value representable as `NonNegativeFiniteNumber` (the lower
100
+ * saturation target of `fromNumber`).
100
101
  */
101
102
  MIN_VALUE,
102
103
 
@@ -117,13 +118,17 @@ export const NonNegativeFiniteNumber = {
117
118
  max: max_,
118
119
 
119
120
  /**
120
- * Clamps a `number` into the `NonNegativeFiniteNumber` range `[MIN_VALUE,
121
- * MAX_VALUE]`.
121
+ * Converts an arbitrary `number` into a `NonNegativeFiniteNumber`, saturating
122
+ * it into the range `[MIN_VALUE, MAX_VALUE]`.
122
123
  *
123
- * @param value - The value to clamp
124
- * @returns The clamped value as a `NonNegativeFiniteNumber`
124
+ * Unlike `asNonNegativeFiniteNumber`, this is total: out-of-range inputs are
125
+ * clamped to the nearest representable `NonNegativeFiniteNumber` instead of
126
+ * throwing.
127
+ *
128
+ * @param value - The value to convert
129
+ * @returns The value as a `NonNegativeFiniteNumber`
125
130
  */
126
- clamp,
131
+ fromNumber,
127
132
 
128
133
  /**
129
134
  * Returns the greatest integer less than or equal to a non-negative finite
@@ -13,8 +13,8 @@ const {
13
13
  MIN_VALUE,
14
14
  add,
15
15
  castType,
16
- clamp,
17
16
  div,
17
+ fromNumber,
18
18
  is,
19
19
  max: max_,
20
20
  min: min_,
@@ -74,12 +74,14 @@ export const NonNegativeInt16 = {
74
74
  is,
75
75
 
76
76
  /**
77
- * The smallest value representable as `NonNegativeInt16`.
77
+ * The smallest value representable as `NonNegativeInt16` (the lower
78
+ * saturation target of `fromNumber`).
78
79
  */
79
80
  MIN_VALUE,
80
81
 
81
82
  /**
82
- * The largest value representable as `NonNegativeInt16`.
83
+ * The largest value representable as `NonNegativeInt16` (the upper saturation
84
+ * target of `fromNumber`).
83
85
  */
84
86
  MAX_VALUE,
85
87
 
@@ -100,13 +102,17 @@ export const NonNegativeInt16 = {
100
102
  max: max_,
101
103
 
102
104
  /**
103
- * Clamps a `number` into the `NonNegativeInt16` range, rounding to the
104
- * nearest integer and constraining the result to `[MIN_VALUE, MAX_VALUE]`.
105
+ * Converts an arbitrary `number` into a `NonNegativeInt16`, rounding to the
106
+ * nearest integer and saturating the result into the range `[MIN_VALUE,
107
+ * MAX_VALUE]`.
105
108
  *
106
- * @param value - The value to clamp
107
- * @returns The clamped value as a `NonNegativeInt16`
109
+ * Unlike `asNonNegativeInt16`, this is total: out-of-range inputs are clamped
110
+ * to the nearest representable `NonNegativeInt16` instead of throwing.
111
+ *
112
+ * @param value - The value to convert
113
+ * @returns The value as a `NonNegativeInt16`
108
114
  */
109
- clamp,
115
+ fromNumber,
110
116
 
111
117
  /**
112
118
  * Generates a random `NonNegativeInt16` within the given range.