TypeScript currently lacks built-in support for numeric range types. The ongoing discussion regarding this feature can be found at microsoft/TypeScript#54925. It remains uncertain whether this functionality will ever be added. In the meantime, using unions of numeric literal types is necessary to represent integer ranges.
Another limitation in TypeScript is the absence of native support for performing mathematical operations on numeric literal types. There's an open feature request addressing this issue at microsoft/TypeScript#26382. Until a solution is implemented, workarounds must be devised to handle such computations within the type system.
Two methods known for enabling mathematical operations with numeric literal types involve manipulating tuple types and details inspected from their length
properties as well as utilizing template literal types along with improved inference capabilities for parsed string literal types. These approaches allow conversion between string and numeric literal types to perform operations by serializing and deserializing numbers through Number.prototype.toString(10)
. While complex, these techniques accommodate various scenarios such as large numbers, negative values, and fractional calculations.
To address negative numbers within your IntRange<F, T>
, incorporating template literals types partially is required. A method for negating a number is demonstrated below:
type Negate<N extends number> =
N extends 0 ? 0 :
`${N}` extends `-${infer S extends number}` ? S :
`-${N}` extends `${infer S extends number}` ? S :
never;
type X = Negate<1.23>;
// type X = -1.23
type Y = Negate<-1.2e-26>
// type Y = 1.2e-26
This snippet interprets the string representation of a number to add or remove a leading "-"
symbol accordingly.
The implementation of IntRange<F, T>
takes into account different scenarios involving both non-negative and negative values, employing tuple types and string manipulations to achieve accurate results.