-
-
Save gaearon/966446d27de88ba4d4806a9a5b291d0a to your computer and use it in GitHub Desktop.
| type UnitInterval = number & { __brand: 'UnitInterval' }; | |
| function makeUnitInterval(x: number): UnitInterval { | |
| if (x >= 0 && x <= 1) { | |
| return x as UnitInterval; | |
| } | |
| throw RangeError('x must be between 0 and 1'); | |
| } | |
| function someFunction(x: UnitInterval): number { | |
| return x ** 2; | |
| } | |
| someFunction(0.5) // Doesn't typecheck | |
| someFunction(1.2) // Doesn't typecheck | |
| someFunction(-1) // Doesn't typecheck | |
| someFunction(makeUnitInterval(0.5)) // Typechecks | |
| someFunction(makeUnitInterval(1.2)) // Also typechecks :( | |
| someFunction(makeUnitInterval(-1)) // Also typechecks :( |
For funsies, you could theoretically add every representable literal to a union and type check that. TypeScript seems to give up after 1x10^-16 and convert to an integer. JS can handle even smaller positive integers, though that would balloon our range to 2^-1024
Assuming typechecking floats literals is about the same effort as typechecking integer literals, it would theoretically take around 14 yottabytes of RAM to typecheck
The numbers are extrapolated from an article I wrote about typechecking a union of 1.8x10^16, and dividing that number by 1.8 to handle our union of size 10^16
https://jacobasper.com/blog/it-takes-26-yottabytes-of-ram-to-typecheck-a-union-of-safe-integers/
So long story short, the UnitInterval dream can be real with enough RAM 😆
It's debatable whether this is "better", but you could also use what is sometimes called a "validator type":