Skip to content

Instantly share code, notes, and snippets.

@trvswgnr
Created September 21, 2021 10:55
Show Gist options
  • Save trvswgnr/94d01695b384d3953e39fd0a198430ee to your computer and use it in GitHub Desktop.
Save trvswgnr/94d01695b384d3953e39fd0a198430ee to your computer and use it in GitHub Desktop.
TypeScript restrict range between two numbers type
type BuildPowersOf2LengthArrays<N extends number, R extends never[][]> =
R[0][N] extends never ? R : BuildPowersOf2LengthArrays<N, [[...R[0], ...R[0]], ...R]>;
type ConcatLargestUntilDone<N extends number, R extends never[][], B extends never[]> =
B["length"] extends N ? B : [...R[0], ...B][N] extends never
? ConcatLargestUntilDone<N, R extends [R[0], ...infer U] ? U extends never[][] ? U : never : never, B>
: ConcatLargestUntilDone<N, R extends [R[0], ...infer U] ? U extends never[][] ? U : never : never, [...R[0], ...B]>;
type Replace<R extends any[], T> = { [K in keyof R]: T }
type TupleOf<T, N extends number> = number extends N ? T[] : {
[K in N]:
BuildPowersOf2LengthArrays<K, [[never]]> extends infer U ? U extends never[][]
? Replace<ConcatLargestUntilDone<K, U, []>, T> : never : never;
}[N]
type RangeOf<MAX extends number> = Partial<TupleOf<unknown, MAX>>["length"];
type Between<From extends number, To extends number> = Exclude<RangeOf<To>, RangeOf<From>> | From;
/*
const getNumber = (x: Between<10, 15>) => console.log(x)
getNumber(29) // Argument of type '29' is not assignable to parameter of type 'Between<10, 15>'.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment