3

I'd like to have a time type (00:00) which is a string that only allows valid times. Consider this Time type working as I like:

const hours = [
  '00' , '01', '02', '03', '04', '05', '06', '07', '08',
  '09' , '10', '11', '12', '13', '14', '15', '16', 
  '17' , '18', '19', '20', '21', '22', '23', '24'
] as const

type HH = typeof hours[number]

const minutes = [
  '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', 
  '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', 
  '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', 
  '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', 
  '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', 
  '50', '51', '52', '53', '54', '55', '56', '57', '58', '59'
] as const 

type MM = typeof minutes[number]

type Time = `${HH}:${MM}`

A cleaner way to write this type can be:

const digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] as const
type Digit = typeof digits[number]
type HH1 = `${Digit}${Digit}` // can be 99, needs to be < 24!
type MM1 = `${Digit}${Digit}` // can be 99, needs to be < 60!
type Time1 = `${HH1}:${MM1}$` // can be 99:99, needs to be max 24:59

So I am trying to use the number array index value of the type typeof digits[number] or the output string value to achieve hours to be < 24 and minutes < 60. Can I use the number value instead of the type or the string value to achieve this in a conditional type?

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47

1 Answers1

1

Since TS 4.5 you can do following :

type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
  ? Acc[number]
  : Enumerate<N, [...Acc, Acc['length']]>

type NumberRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>>

type Time = NumberRange<0, 59> // 0...59

That's until, we get ranges as number type in TS.

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134