Home > Blockchain >  How to define a type with sequence numbers in TypeScript
How to define a type with sequence numbers in TypeScript

Time:12-24

I want to define a type with 1-31, such as :

type DAYS = 1 | 2 | .... | 31;

So, has some methods like this ?

type DAYS = 1..31;

CodePudding user response:

No, you'll have to write these by hand. See more here.

Of course, you could write a code-gen tool if you have a lot of these, but it seems like an overkill.

CodePudding user response:

As mentioned in the other, correct, answer, there is no such feature provided by the language, and microsoft/TypeScript#15480 is the relevant open feature request.

If you are using TypeScript 4.5 , and your ranges are non-negative whole numbers less than 1000 and you don't mind making the compiler go through a lot of effort to calculate small numbers, you can use a recursive conditional type that use variadic tuples to build up arrays of arrays of varying lengths, and then get a union of those lengths:

type LessThan<N extends number, A extends any[] = []> =
  N extends A['length'] ? A[number] : LessThan<N, [...A, A['length']]>

type NumericRange<F extends number, T extends number> = 
  Exclude<T | LessThan<T>, LessThan<F>>

You can try it on your Days type, and it works:

type Days = NumericRange<1, 31>
/* type Days = 1 | 31 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
   16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 */

Note that union ordering is an implementation detail, and the compiler tends to put types it's already seen before earlier in the union, so this is correct (every number from 1 to 31 is present) but weird (since the 31 shows up after the 1 and before the 2).

Of course if you're only using it once, to create Days then it's definitely not worth it, since there are more characters in the implementation of NumericRange than there are in writing out the Days type manually.

Playground link to code

  • Related