08640-medium-number-range

Back

use Exclude

type NumberToUnion<
  N extends number,
  Arr extends any[] = [],
  Ret = 0
> = Arr["length"] extends N
  ? Ret
  : NumberToUnion<N, [...Arr, any], Ret | [...Arr, any]["length"]>;

type NumberRange<Start extends number, End extends number> =
  | Exclude<NumberToUnion<End>, NumberToUnion<Start>>
  | Start;

Solution by sunupupup #33436

type NumberToArr<
  N extends number,
  Arr extends any[] = []
> = Arr["length"] extends N ? Arr : NumberToArr<N, [...Arr, any]>;

type NumberRange<
  Start extends number,
  End extends number,
  StartArr extends any[] = NumberToArr<Start>,
  EndArr extends any[] = NumberToArr<End>,
  Ret extends number[] = []
> = StartArr["length"] extends EndArr["length"] 
                       ? [...Ret, StartArr["length"]][number]
                       : NumberRange<Start, End, [...StartArr, any], EndArr, [...Ret, StartArr["length"]]>

Solution by sunupupup #33435

type NumberArray<
  N extends number,
  A extends number[] = []
> = A["length"] extends N ? A : NumberArray<N, [...A, A["length"]]>;

type UnionUtilNumber<N extends number> =
  NumberArray<N> extends infer T extends number[] ? T[number] : never;

type NumberRange<L extends number, H extends number> = Exclude<
  H | UnionUtilNumber<H>,
  UnionUtilNumber<L>
>;

Solution by SCUTBrothers #33384

// answer 1
type NumberRange<L extends number, H extends number, LR extends any[] = [], R extends any[] = []> = LR['length'] extends L
  ? [...LR, ...R]['length'] extends H
    ? R[number] | H
    : NumberRange<L, H, LR, [...R, [...LR, ...R]['length']]>
  : NumberRange<L, H, [...LR, LR['length']], R>
// answer 2
type Exclude<T, U> = T extends U ? never : T

type NUnion<T extends number, R extends any[] = []> = R['length'] extends T ? R[number] : NUnion<T, [...R, R['length']]>

type NumberRange<L extends number, H extends number> =  Exclude<NUnion<H>, NUnion<L>> | H

Solution by rimo030 #32875

type NumberRange<
  L,
  H,
  A extends number[] = [],
  B extends number[] = []
> = H extends L
  ? [...B, A["length"]][number]
  : L extends A["length"]
  ? NumberRange<[...A, 1]["length"], H, [...A, 1], [...B, A["length"]]>
  : NumberRange<L, H, [...A, 1], B>;

Solution by GodCount #32426

type ConstructTuple<L extends number, M extends Array<unknown> = []> = L extends M["length"]
	? M
	: ConstructTuple<L, [unknown, ...M]>;

type NumberRange<L extends number, H extends number, N extends Array<unknown[]> = [ConstructTuple<L>]> = N extends [
	...infer _,
	infer Last,
]
	? Last extends Array<unknown>
		? Last["length"] extends H
			? N[number]["length"]
			: NumberRange<L, H, [...N, [...ConstructTuple<Last["length"]>, unknown]]>
		: never
	: never;

Solution by gasmg #32354

type Increment<A extends unknown[]> = [...A, A['length']];

type Times<Limit extends number, Acc extends unknown[] = []> = Acc['length'] extends Limit 
  ?
    Increment<Acc>
  : 
    Times<Limit, Increment<Acc>>


type Shift<A extends unknown[], End extends number, Acc extends unknown[] = []> = A extends [infer H, ...infer T] 
  ? 
    H extends End
      ?
        [H, ...T][number]
      :
        Shift<T, End, [...Acc, H]>
  :
    never;


type NumberRange<L extends number, H extends number> = Shift<Times<H>, L>

Solution by keyurparalkar #32309

type ConstructTuple<
  L extends number,
  R extends unknown[] = []
> = R["length"] extends L ? R : ConstructTuple<L, [...R, never]>;

type NumberRange<
  L extends number,
  H,
  A extends unknown[] = ConstructTuple<L>
> = A["length"] extends H
  ? [...A, A["length"]][number]
  : NumberRange<L, H, [...A, A["length"]]>;

Solution by vangie #32190

type Max<T extends number[], U = T[number], N extends any[] = []> = 
    Equal<U, N['length']> extends true 
    ? U
    : Max<T, (U extends N['length'] ? never : U), [...N, unknown]>

type NumberRange<L extends number, H extends number, Ans extends number[] = []> = 
  Ans["length"] extends H
    ? [...Ans, H][number]
    : NumberRange<Max<[L, [...Ans, L]["length"]]>, H, [...Ans, L]>

Solution by kanemototomoki #31772

type MinusOne<T extends number> = ParseInt<RemoveLeadingZeros<ReverseString<InternalMinusOne<ReverseString<`${T}`>>>>>;
type ReverseString<S extends string> = S extends `${infer First}${infer Rest}` ? `${ReverseString<Rest>}${First}` : '';
type InternalMinusOne<
  S extends string
> = S extends `${infer Digit extends number}${infer Rest}` ?
    Digit extends 0 ?
      `9${InternalMinusOne<Rest>}` :
    `${[9, 0, 1, 2, 3, 4, 5, 6, 7, 8][Digit]}${Rest}`:
  never;
type RemoveLeadingZeros<S extends string> = S extends '0' ? S : S extends `${'0'}${infer R}` ? RemoveLeadingZeros<R> : S;
type ParseInt<T extends string> = T extends `${infer Digit extends number}` ? Digit : never;

type NumberRange<L extends number, H extends number> = 
  H extends L ? H : NumberRange<L, MinusOne<H>> | H;

The following code will create a number range, but only up to a difference of about 40. e.g. type t = NumberRange<1011, 1054>

Solution by KNHui #31528

type MinusOne<N extends number, R extends boolean[] = []> = 
  N extends 0 ? 0 :
  R['length'] extends N ?
  R extends [infer _, ...infer Rest] ? 
  Rest['length'] :
  R['length'] :
  MinusOne<N, [...R, true]>

type NumberRange<S extends number, L extends number, Result extends number[] = []> = 
  L extends S ?
  [...Result, S][number] :
  NumberRange<S, MinusOne<L>, [...Result, L]>

type res = NumberRange<2, 9>
type minus = MinusOne<0>
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<NumberRange<2, 9>, Result1>>,
  Expect<Equal<NumberRange<0, 2>, Result2>>,
  Expect<Equal<NumberRange<0, 140>, Result3>>,
]

Solution by gearonix #31399

// Create Array specified length
type NumberedArray<T extends number, Arr extends number[] = []> = T extends 0 ? [] :
  Arr['length'] extends T ? [...Arr, Arr['length']] : NumberedArray<T, [...Arr, Arr['length']]>
// Create Array specified length - 1
type NumberedArrayExcludeLast<T extends number, Arr extends number[] = []> = T extends 0 ? [] :
  Arr['length'] extends T ? Arr : NumberedArrayExcludeLast<T, [...Arr, Arr['length']]>

// Exclude<0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9, 0 | 1 >
type NumberRange<L extends number, H extends number> = Exclude<NumberedArray<H>[number], NumberedArrayExcludeLast<L>[number]>

Solution by hwasurr #31386

// your answers
type UnionFromNumber<L extends number, Ans extends unknown[] = []> =  Ans["length"] extends L ? Ans[number] : UnionFromNumber<L, [...Ans, Ans["length"]]>

type NumberRange<L extends number, H extends number> = Exclude<UnionFromNumber<H>, UnionFromNumber<L>> | H

UnionFromNumber<L> generates a union type of 0 | 1 | ... | L-1. Therefore, using Exclude<UnionFromNumber<H>, UnionFromNumber<L>> yields a type of H | H + 1 | ... | L-2 | L-1. To include L in the type, we simply append L at the end.

Solution by Kakeru-Miyazaki #30895

type MakeNumberToArray<T extends number, U extends unknown[] = []> = U['length'] extends T
  ? U
  : MakeNumberToArray<T, [...U, unknown]>;

type GreaterThanOrEqual<T extends number, U extends number> = MakeNumberToArray<T> extends [
  ...MakeNumberToArray<U>,
  ...infer _,
]
  ? true
  : false;

type NumberRange<
  T extends number,
  U extends number,
  M extends unknown[] = MakeNumberToArray<T>,
  N extends unknown[] = MakeNumberToArray<U>,
  R extends unknown[] = [],
> = GreaterThanOrEqual<N['length'], T> extends true
  ? N extends [infer _, ...infer Rest]
    ? NumberRange<T, U, M, Rest, [...R, N['length']]>
    : [...R, 0][number]
  : R[number];

Solution by leejaehyup #30853

type NumberRange<L, H, U extends number[] = [], O extends number[] = [], Flag = O['length'] extends L ? true : false> =  Flag extends true 
? U extends [...infer A, infer B] 
? B extends H 
? U[number] 
: NumberRange<L, H, [...U, O['length']], [...O, 1], true>
: NumberRange<L, H, [...U, O['length']], [...O, 1], true>
: NumberRange<L, H, U, [...O, 1], [...O, 1]['length'] extends L ? true : Flag>

Solution by dreamluo-plus #30678

type markArr<L,R extends any[] = []> = L extends R['length'] ?R : markArr<L,[...R,R['length']]>

type plus<V> = [0,...markArr<V>]["length"];

type NumberRange<L extends any, H extends number,R extends any[] = [L]> = H extends plus<L> ? [...R,plus<L>][number]:NumberRange<plus<L>,H,[...R,plus<L>]>  

Solution by jiangxd2016 #30551

维护三个参数 1.StartList用来收集元素, 一直到length满足起始值为止 2.EndList用来收集元素,一直到length满足结束值为止 3.R作为返回的联合类型, 每当StartList['length']满足起始值, 在递归的时候, 就用EndList['length'] 与 R进行联合 4.当EndList['length']满足结束值, 把之前收集的联合类型R与当前EndList['length']进行联合, 并返回

type NumberRange<L, H, EndList extends any[] = [], StartList extends any[] = [], R = L> = 
  StartList['length'] extends L
    ? EndList['length'] extends H
      ? R | EndList['length']
      : NumberRange<L, H, [...EndList, 1], StartList, R | EndList['length']>
    : NumberRange<L, H, [...EndList, 1], [...StartList, 1], R>

Solution by xiahouwei #30545

// 使用了3个参数,R用于记录结果,A用于计数,B用于记录当前是否在指定范围
// A逐渐累加,当与L相等时B设置为true
type NumberRange<L, H, R=never, A extends any[]=[], B extends boolean = false> = 
  L extends A['length']?
    NumberRange<L,H, R|A['length'], [1, ...A], true>
    :H extends A['length']? 
      R|A['length']
      : B extends true
        ? NumberRange<L,H, R|A['length'], [1, ...A], true>
        :NumberRange<L,H, R, [1,...A, false]>

Solution by yangyyou #30467

type PlusOne<T extends number, Len extends number = 0, Acc extends number[] = []> = T extends Len ?
  [...Acc, T]['length'] :
  PlusOne<T, [...Acc, T]['length'], [...Acc, T]>;


type Tail<T extends unknown[]> = T extends [...infer R, infer L] ? L : never;


type NumberRange<L extends number, H extends number, Acc extends number[] = [L]> = Tail<Acc> extends H ? Acc[number] : NumberRange<PlusOne<L>, H, [...Acc, PlusOne<L>]>;

Solution by dimitriiy #30424

type NumberRange<
  L, 
  H,
  I extends any[] = [],
  F = I['length'] extends L ? true : false
> = I['length'] extends H
  ? I[number] | H
  : F extends false
    ? NumberRange<L, H, [...I, never]>
    : NumberRange<L, H, [...I, I['length']], true>

Solution by wangtunan #30251

type N<T extends 0[] = []> = {
  '0': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T],
  '1': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0],
  '2': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0],
  '3': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0],
  '4': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0],
  '5': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0, 0],
  '6': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0, 0, 0],
  '7': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0, 0, 0, 0],
  '8': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0, 0, 0, 0, 0],
  '9': [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, 0, 0, 0, 0, 0, 0, 0, 0, 0],
}

type NumberRange<L extends number, H extends number, F extends string = `${L}`, R extends 0[] = [], T extends any[] = [], S extends number[] = []> = 
  F extends `${infer A}${infer Rest}`
    ? 
      NumberRange<L, H, Rest, N<R>[keyof N & A], T, S>
    : T extends [...infer B, infer C extends 0[]]
      ?
        C['length'] extends H
          ?
            S[number]
          : NumberRange<L, H, F, R, [...T, [...C, 0]], [...S, [...C, 0]['length']]>
      : NumberRange<L, H, F, R, [...T, R], [...S, R['length']]>

Solution by zhangqiangzgz #30216

// your answers
// 这是增加了一个结果数组U
// 如果U的长度和T相等,会返回U[number],即U数组的元素的联合类型,此时U里面是有T个元素
// 接下来是要按照正整数一个个从0自增放进入数组U
// 否则递归调用,U中放入其他元素,和一个U['length'],即最先会放入一个0,U变为[0]
// 然后U中元素依次增加,加入的元素依次变为0,1,2,3...直到T个
// 最后NumberRange中,使用Exclude,先拿到H个,从其中剔除L个
// 但是此时是不会包含H这个值的,需要再联合起来
type LengthArray<T extends number, U extends unknown[] = []> = Equal<
	T,
	U['length']
> extends true
	? U[number]
	: LengthArray<T, [...U, U['length']]>
type NumberRange<L extends number, H extends number> =
	| Exclude<LengthArray<H>, LengthArray<L>>
	| H

Solution by bebusy007 #30083

type NewArray<T extends number, S extends any[] = []> = S['length'] extends T ?
    S : NewArray<T, [...S, 0]>;

type NumberRange<T extends number, E extends number, R extends number[] = [], S extends any[] = NewArray<T>> =
    S['length'] extends E ?
        [...R, S['length']][number]:
        NumberRange<T, E, [...R, S['length']], [...S, 0]>;

type numberRange = NumberRange<2, 9>;

const numRange: numberRange = 8;

Solution by sundial-dreams #29560

  type Utils<L, C extends any[] = [], R = L> = 
  C['length'] extends L
      ? R
      : Utils<L, [...C, 0], C['length'] | R>

type NumberRange<L, H> = L | Exclude<Utils<H>, Utils<L>>

Solution by DoubleWoodLin #28785

type Range<
  Limit extends number,
  Numbers extends number[] = []
> = Numbers["length"] extends Limit
  ? [...Numbers, Numbers["length"]][number]
  : Range<Limit, [...Numbers, Numbers["length"]]>;

type NumberRange<From extends number, To extends number> =
  | From
  | Exclude<Range<To>, Range<From>>;

Solution by yevhenpavliuk #28388

// your answers
type NumberRange<L, H, Run extends any[] = [], Arr extends any[] = []> = Run['length'] extends L
? Arr['length'] extends H
  ? Exclude<[...Arr, Arr['length']][number], never>
  : NumberRange<L, H, Run, [...Arr, Arr['length']]>
: NumberRange<L, H, [...Run, any], [...Arr, never]>;

Solution by ixiaolong2023 #27864

type NumberRange<
  L extends number,
  H extends number,
  Acc extends number = never,
  CountArr extends 0[] = [],
  ReachedStart extends boolean = Equal<CountArr["length"], L>,
  ReachedEnd extends boolean = Equal<[...CountArr, 0]["length"], H>
> = ReachedEnd extends true
  ? Acc
  : NumberRange<
      L,
      H,
      ReachedStart extends true ? Acc | CountArr["length"] : Acc,
      [...CountArr, 0],
      ReachedStart extends true ? true : Equal<[...CountArr, 0]["length"], L>,
      ReachedEnd extends true ? true : Equal<CountArr["length"], H>
    >;

Solution by alythobani #27612

type NumToArr<N extends number, P extends number[] = []> =
  P['length'] extends N ? P : NumToArr<N, [...P, P['length']]>

type Shift<T extends Array<any>> =
  T extends [infer _, ...infer R] ? R : []

type NumberRange<
  L extends number,
  H extends number,
  K extends number[] = NumToArr<L>,
  P extends number[] = NumToArr<H>
> =
  K extends []
    ? [...P, H][number]
    : NumberRange<L, H, Shift<K>, Shift<P>>

Solution by smileboyi #27155

type NumberRange<L extends number, H extends number,arr extends number[] = [],bol extends boolean = false> = 
 bol extends true ? arr['length'] extends H ? arr[number] : NumberRange<L,H,[...arr,arr['length']],true> : 
 arr['length'] extends H ? NumberRange<L,H,[...arr,arr['length']],true> : NumberRange<L,H,[...arr,L],false>

Solution by WangZiChu199910252255 #26900

// your answers
type MinusOne<T extends number, Count extends unknown[] = []> = 
  Count['length'] extends T 
  ? Count extends [unknown, ...infer Tail] 
    ? Tail['length'] 
    : never 
  : MinusOne<T, [...Count, unknown]>;


type NumberRange<L extends number, H extends number, Res extends number[] = [L]> = 
  L extends H
  ? Res[number] // obtain a union type
  : NumberRange<L, MinusOne<H>, [...Res, H]>

Solution by kiki-zjq #25711