Skip to content

Instantly share code, notes, and snippets.

@insyri
Created May 12, 2022 15:48
Show Gist options
  • Save insyri/682868f141425e0263f042cdfd178c63 to your computer and use it in GitHub Desktop.
Save insyri/682868f141425e0263f042cdfd178c63 to your computer and use it in GitHub Desktop.
attempt at making a type level cron validation, licensed under WTFPL, but reference me for inspiration somewhere
type Length<T extends any[]> = T extends {length: infer L} ? L: never;
type BuildTuple<L extends number, T extends any[] = []> = T extends {length: L} ? T: BuildTuple<L, [...T, any]>;
type Subtract<A extends number, B extends number> = BuildTuple<A> extends [...(infer U), ...BuildTuple<B>] ? Length<U> : never;
// prettier-ignore
type To59 = 0 | 1 | 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 | 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;
// prettier-ignore
type To31 = Exclude<To59, 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>
type To30 = Exclude<To31, 31>;
// prettier-ignore
type To28 = Exclude<To30, 30 | 29>;
// prettier-ignore
type To23 = Exclude<To28, 27 | 26 | 25 | 24>
// prettier-ignore
type To12 = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
// prettier-ignore
type To7 = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
// prettier-ignore
// enum Month {
// Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
// }
type StringMonth = keyof typeof Month;
enum Month {
Jan = 31,
Feb = 28,
Mar = 31,
Apr = 30,
May = 31,
Jun = 30,
Jul = 31,
Aug = 30,
Sep = 31,
Oct = 30,
Nov = 31,
Dec = 30
}
// prettier-ignore
enum Days {
Mon, Tue, Wed, Thu, Fri, Sat, Sun
}
type StringDay = keyof typeof Days;
type Second = To59
type Minute = To59
type Hour = To12
// type DayOfWeek = StringDay | Days;
// `second minute hour day month year?`
type AnyTimeUnspecific = To59 | To23 | To31 | To12 | To7 | StringMonth | StringDay;
type AnyTimeNumber = Exclude<AnyTimeUnspecific, StringMonth | StringDay>;
type AnyTimeSpecific<T extends AnyTimeUnspecific> = T;
type PutInBetweenSpecific<T1 extends string, S extends string, T2 extends string> = `${T1}${S}${T2}`;
// type PutInBetween<S extends string, T extends string> = `${T}${S}${T}`;
type Opt<T> = T | '*';
/**
* 1
* 1-1
*/
let j = 3;
// type Segment<T extends > = `${T}${"" | ''}`
// type CronRange<From extends AnyTimeUnspecific, To extends From> =
// From extends number ? (To extends number ? (Subtract<From, To> ? PutInBetweenSpecific<'-', `${From}`, `${To}`> : never): never) :
// From extends string ? (To extends string ? PutInBetweenSpecific<'-', From, To> : never) : never;
type CronRangeNumber<From extends AnyTimeNumber, To extends From> =
From extends To12 ? (Subtract<From, To> extends number ? Subtract<From, To> : never) : never;
// type SecondRange = CronRange<To12, To12>
// let sr: SecondRange = ;
// type Range<T extends AnyTimeUnspecific> =
// Subtract<T, T> extends number ? Subtract<T, T> : never;
// type Interval<T extends AnyTimeUnspecific> =
// PutInBetween<'/', AnyTimeSpecific<T>>;
// type Listed<T extends AnyTimeUnspecific> = `${AnyTimeSpecific<T>}`;
// type VariantOf<T extends AnyTimeUnspecific> = Range<T> | Interval<T> | Listed<T>;
/**
* ```txt
* ┌───── Second (0-59)
* │ ┌───── Min (0-59 or *)
* │ │ ┌───── Hour (0-23 or *)
* │ │ │ ┌───── Day of Month (1-31 or *)
* │ │ │ │ ┌───── Month (1-12, Jan-Dec, or *)
* │ │ │ │ │ ┌───── Day of Week (1-7, Mon-Sun, or *)
* │ │ │ │ │ │ ┌───── Year (optional, default: *)
* │ │ │ │ │ │ │
* * * * * * * *
* ```
*/
// export type CronDay = `${Second} ${Opt<Minute>} ${Opt<Hour>}`;
// export type CronMonth<M extends Month> = `${Opt<DayOf>} ${Opt<Month>}`
// type Something<T1 extends number, T2 extends number> = T1 > T2 ? T1 : T2;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment