type NumberRange<
L,
H,
Count extends any[] = [],
Res extends any[] = [],
Flag extends boolean = Count['length'] extends L ? true : false
> = Flag extends true
? Count['length'] extends H
? [...Res, Count['length']][number]
: NumberRange<L, H, [...Count, Count['length']], [...Res, Count['length']], Flag>
: NumberRange<L, H, [...Count, '']>;
Solution by wendao-liu #35090
type NumberRange<L, H, R extends unknown[] = []> = H extends R[0] ? R[number] : L extends R['length'] ? NumberRange<[any, ...R]['length'], H, [R['length'], ...R]> : NumberRange<L, H, [never, ...R]>
Solution by 2083335157 #34936
type NumberRange<L, H, R=never, P extends unknown[]=[]> =
[R] extends [never] ? P["length"] extends L ? NumberRange<L, H, P["length"], [unknown, ...P]> : NumberRange<L, H, never, [unknown, ...P]> :
P["length"] extends H ? R|P["length"] : NumberRange<L, H, R|P["length"], [unknown, ...P]>;
思路: R中存放临时结果,P中存放数组,用P数组的长度来表示L~H的数字,
Solution by ndfhsledk #34453
// your answers
type NumberToArray<N extends number, T extends any[] = []> = T['length'] extends N ? T : NumberToArray<N, [...T, 1]>;
type NumberRange<L extends number, H extends number, T extends any[] = NumberToArray
Solution by DiracKeeko #34167
type NumberRange<L, H, C extends 1[] = [], R extends number[] = [], F = C['length'] extends L ? true : false> =
F extends true ? (C['length'] extends H ? [...R, C['length']][number] : NumberRange<L, H, [...C, 1], [...R, C['length']], true>) : NumberRange<L, H, [...C, 1]>
Solution by ouzexi #34102
// your answers
type NumberRange<L, H, Res extends any[] = [], Flag extends boolean = Res['length'] extends L ? true : false> =
Res['length'] extends H ? [...Res, H][number] :
Flag extends true ? NumberRange<L, H, [...Res, Res['length']], Flag> : NumberRange<L, H, [...Res, never]>
Solution by heyuelan #33868
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 gearonixx #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