gvergnaud / hotscript

A library of composable functions for the type-level! Transform your TypeScript types in any way you want using functions you already know.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Enumerate and Range

AnatoleLucet opened this issue · comments

Great suggestion

@gvergnaud @AnatoleLucet I just realized that one of the issues I opened duplicates this one: #37

I'll close that one and continue the discussion here:


Definition

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

type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>> | T;

Usage

type CustomRange = IntRange<20, 300>; // -> 20 | 21 | ... many more ... | 300

Disclaimer & credit

This type is inspired (99% copied) from this StackOverflow answer by AlexG, with a slight modification to include the last number in the series (| T). Without this change, IntRange<20, 300> would match 20–299 instead or 20–300.

Per that last disclaimer, I think it could be more intuitive to include the last/max number. So instead of IntRange<100, 200>, we could use IntRange<100, 199>.

We could even make the option of whether to include the end or not a second boolean arg, which I personally think should default to true. With that enabled, if you wanted to keep the min and max values the same and not use the "…99" values, you could do this—

type Informational = IntRange<100, 200, false>;

This would work identically to the previous example. Here is the modified type to support that:

type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
  ? Acc[number]
  : Enumerate<N, [...Acc, Acc['length']]>;
type IntRange<F extends number, T extends number, IncludeEnd = true> = IncludeEnd extends true ? (Exclude<Enumerate<T>, Enumerate<F>> | T) : (Exclude<Enumerate<T>, Enumerate<F>>);

type WithEnd    = IntRange<20, 300>;        // -> 20 | 21 | ... many more ... | 300
type WithoutEnd = IntRange<20, 300, false>; // -> 20 | 21 | ... many more ... | 299

Hey! This is related to the PR I opened adding a Tuples.Range function: #40

I think we should implement Unions.Range in terms of Tuples.Range

Well, here is a PR doing this: #41

(closing because this has been implemented)