type TupleFromLength<N extends number, Result extends 0[] = []> = Result["length"] extends N
? Result
: TupleFromLength<N, [...Result, 0]>;
type InclusiveRange<
Lower extends number,
Higher extends number,
LowerTuple extends 0[] = TupleFromLength<Lower>,
HigherTuple extends 0[] = TupleFromLength<Higher>,
Counter extends 0[] = [],
Result extends number[] = []
> = Counter extends [...LowerTuple, ...0[]]
? Counter extends [...HigherTuple, 0, ...0[]]
? Result
: InclusiveRange<Lower, Higher, LowerTuple, HigherTuple, [...Counter, 0], [...Result, Counter["length"]]>
: Counter extends [...HigherTuple, ...unknown[]]
? Result
: InclusiveRange<Lower, Higher, LowerTuple, HigherTuple, [...Counter, 0], Result>;
Solution by yukicountry #34534
After first time "N extends L", changes L to number
, after then "N extends L" always true
type InclusiveRange<
L extends number,
H extends number,
T extends 1[] = [],
R extends number[] = [],
N extends number = T['length']
> = N extends H
? N extends L ? [...R, N] : R
: N extends L
? InclusiveRange<number, H, [...T, 1], [...R, N]>
: InclusiveRange<L, H, [...T, 1], R>;
Solution by alexandroppolus #32271
// 解答をここに記入
type GenArr<N extends number, Ans extends number[] = []> = Ans["length"] extends N ? Ans : GenArr<N, [...Ans, Ans["length"]]>
type InclusiveRange<Lower extends number, Higher extends number> = GenArr<Higher> extends [...GenArr<Lower>, ...infer R] ? [...R, Higher] : []
type cases = [
Expect<Equal<InclusiveRange<200, 1>, []>>,
Expect<Equal<InclusiveRange<10, 5>, []>>,
Expect<Equal<InclusiveRange<5, 5>, [5]>>,
Expect<Equal<InclusiveRange<0, 10>, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>,
Expect<Equal<InclusiveRange<1, 200>, [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, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]>>,
Expect<Equal<InclusiveRange<22, 146>, [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, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146]>>,
]
Solution by Kakeru-Miyazaki #30999
enum Comparison {
Greater,
Equal,
Lower,
}
type JudgeMap = [
'1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9',
'2' | '3' | '4' | '5' | '6' | '7' | '8' | '9',
'3' | '4' | '5' | '6' | '7' | '8' | '9',
'4' | '5' | '6' | '7' | '8' | '9',
'5' | '6' | '7' | '8' | '9',
'6' | '7' | '8' | '9',
'7' | '8' | '9',
'8' | '9',
'9',
never
];
type JudgeOne<A extends string, B extends string> = B extends A
? Comparison.Equal
: B extends keyof JudgeMap
? A extends JudgeMap[B]
? Comparison.Greater
: Comparison.Lower
: Comparison.Equal;
type GetEmpty<A extends string> = A extends `${infer E}${infer R}`
? `.${GetEmpty<R>}`
: '';
type JudgeTemplate<A extends string, B extends string> = A extends B
? Comparison.Equal
: A extends `${infer L}${B}${infer R}`
? Comparison.Greater
: Comparison.Lower;
type JudgeLength<A extends string, B extends string> = JudgeTemplate<
GetEmpty<A>,
GetEmpty<B>
>;
type JudgeString<A extends string, B extends string> = JudgeLength<
A,
B
> extends Comparison.Equal
? A extends `${infer A1}${infer A2}`
? B extends `${infer B1}${infer B2}`
? JudgeOne<A1, B1> extends Comparison.Equal
? JudgeString<A2, B2>
: JudgeOne<A1, B1>
: Comparison.Equal
: Comparison.Equal
: JudgeLength<A, B>;
type Comparator<
A extends number,
B extends number
> = `${A}` extends `-${infer T1}`
? `${B}` extends `-${infer T2}`
? JudgeString<T2, T1>
: Comparison.Lower
: `${B}` extends `-${infer T2}`
? Comparison.Greater
: JudgeString<`${A}`, `${B}`>;
type GetArray<T extends number, O extends 1[] = []> = O['length'] extends T
? O
: GetArray<T, [1, ...O]>;
// get 5 numbers at a time
type InclusiveRange<
Lower extends number,
Higher extends number,
H extends 1[] = GetArray<Lower>
> = Comparator<Lower, Higher> extends Comparison.Greater
? []
: H['length'] extends Higher
? [Higher]
: [1, ...H]['length'] extends Higher
? [H['length'], Higher]
: [1, 1, ...H]['length'] extends Higher
? [H['length'], [1, ...H]['length'], Higher]
: [1, 1, 1, ...H]['length'] extends Higher
? [H['length'], [1, ...H]['length'], [1, 1, ...H]['length'], Higher]
: [1, 1, 1, 1, ...H]['length'] extends Higher
? [
H['length'],
[1, ...H]['length'],
[1, 1, ...H]['length'],
[1, 1, 1, ...H]['length'],
Higher
]
: [
H['length'],
[1, ...H]['length'],
[1, 1, ...H]['length'],
[1, 1, 1, ...H]['length'],
[1, 1, 1, 1, ...H]['length'],
...InclusiveRange<Lower, Higher, [1, 1, 1, 1, 1, ...H]>
];
type A = InclusiveRange<1, 190>;
Solution by Royce-DaDaDa #29932
type GreatThanByLength<A extends string,B extends string> =
A extends `${string}${infer AR}`?
B extends `${string}${infer BR}`?
GreatThanByLength<AR,BR>
: 1
:
B extends ''? 0: -1
type GreatThanByDigitConfig = {
'0':never;
'1': '0',
'2': '0' | '1',
'3': '0' | '1' | '2',
'4': '0' | '1' | '2' | '3',
'5': '0' | '1' | '2' | '3' | '4',
'6': '0' | '1' | '2' | '3' | '4' | '5',
'7': '0' | '1' | '2' | '3' | '4' | '5' | '6',
'8': '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7',
'9': '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'
}
type GreatThanBydigit<A extends string,B extends string> =
A extends keyof GreatThanByDigitConfig?
B extends GreatThanByDigitConfig[A]? true:false
:false
type GreatThanByDigits<A extends string,B extends string> =
A extends `${infer AF}${infer AR}`?
B extends `${infer BF}${infer BR}`?
AF extends BF?
GreatThanByDigits<AR,BR>
: GreatThanBydigit<AF,BF>
:false
:false
type GreatThan<A extends number,B extends number> =
A extends B?
false:
GreatThanByLength<`${A}`,`${B}`> extends infer C?
C extends 1?
true:
C extends 0?
GreatThanByDigits<`${A}`,`${B}`>
:false
:never
type MakeTuple<T extends number,R extends number[] = []> =
R['length'] extends T ?
R:MakeTuple<T,[...R,0]>
type Range<L extends number,H extends number,R extends number[] = [],C extends number[] = MakeTuple<L> > =
C['length'] extends H?
[...R,H]
:Range<L,H,[...R,C['length']],[...C,0]>
type InclusiveRange<Lower extends number, Higher extends number> =
GreatThan<Lower,Higher> extends true?
[]:Range<Lower,Higher>
Solution by jiangshanmeta #28534
type InclusiveRange<Lower extends number, Higher extends number, C extends 0[] = [], R extends number[] = []> =
C['length'] extends Lower
? C['length'] extends Higher
? [Lower]
: InclusiveRange<Lower, Higher, [0, ...C], [C['length']]>
: C['length'] extends Higher
? R['length'] extends 0
? []
: [...R, Higher]
: R['length'] extends 0
? InclusiveRange<Lower, Higher, [0, ...C], R>
: InclusiveRange<Lower, Higher, [0, ...C], [...R, C['length']]>
Solution by RuyiLi #27900
type InclusiveRange<
Lower extends number,
Higher extends number,
L extends 1[] = [],
R extends number[] = []
> = L['length'] extends Higher
? Lower extends Higher
? [Lower]
: Lower extends 0
? [...R, L['length']]
: []
: Lower extends 0 | L['length']
? InclusiveRange<0, Higher, [...L, 1], [...R, L['length']]>
: InclusiveRange<Lower, Higher, [...L, 1]>;
Solution by JohnLi1999 #27820
/**加法器部分 */
namespace Adder {
/**0~9 */
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
/**个位 RRRF ==> F */
type DigitFirst<T extends string | number | bigint> = T extends string ?
(Number<T> extends Digit ?
Number<T> :
(T extends `${number}${infer R}` ? DigitFirst<R> : never)) :
DigitFirst<`${T}`>;
/**个位以上 RRRF ==> RRR */
type DigitRest<T extends string | number | bigint, _Result extends string = ``> = T extends string ?
(T extends `${infer F}${infer R extends `${any}${any}`}` ?
DigitRest<R, `${_Result}${F}`> :
Number<_Result> extends 0/*去0*/ ? `` : _Result) :
DigitRest<`${T}`>;
type MakeCounter<T extends number, _Result extends 1[] = []> = _Result[`length`] extends T ? _Result : MakeCounter<T, [..._Result, 1]>;
/**个位相加 */
type DigitAdd<X extends Digit, Y extends Digit> = [...MakeCounter<X>, ...MakeCounter<Y>][`length`] extends (infer N extends number) ? N : 0;
/**Parse Int */
type Number<T extends string | number | bigint> = T extends `0${infer R}`/*去0*/ ? Number<R> : T extends `${infer N extends number | bigint}` ? N : 0;
/**+1 */
export type AddOne<T extends number | string, _DigitAdd extends number = DigitAdd<DigitFirst<T>, 1>> = Number<`${_DigitAdd extends Digit ? DigitRest<T> : /*进位*/AddOne<DigitRest<T>>}${DigitFirst<_DigitAdd>}`>;
}
/**比较器部分 */
namespace Comparator {
type Digit = ToArray<`0123456789`>;
type ToArray<T extends string | number | bigint> = `${T}` extends `${infer F}${infer R}` ? [F, ...ToArray<R>] : [];
type Length<T extends number | bigint | string> = ToArray<T>["length"];
/**最高位 */
type High<T extends string | number | bigint> = `${T}` extends `${infer F}${any}` ? F : ``;
/**更低位 */
type DigitLowerRest<T extends number | bigint | string> = `${T}` extends `${any}${infer R}` ? R : ``;
/**绝对值 */
type AbsString<T extends number | string | bigint> = `${T}` extends `-${infer N}` ? N : `${T}`;
/**是否负数 */
type IsNegative<T extends number | string | bigint> = `${T}` extends `-${any}` ? true : false;
/**比较单个位 */
type DigitComparator<T1 extends number | bigint | string, T2 extends number | bigint | string, IsNegative extends boolean = false, U extends string[] = Digit> =
(T1 extends T2 ?
Comparison.Equal :
(AbsString<T1> extends U[0] ?
(IsNegative extends false ? Comparison.Lower : Comparison.Greater) : //负值反转
(AbsString<T2> extends U[0] ?
(IsNegative extends false ? Comparison.Greater : Comparison.Lower) : //负值反转
(U extends [any, ...infer R extends string[]] ? DigitComparator<T1, T2, IsNegative, R> : false)
))
);
export enum Comparison {
Greater,
Equal,
Lower,
}
export type Comparator<A extends number | bigint | string, B extends number | bigint | string, _AIsNegative extends boolean = IsNegative<A>, _BIsNegative extends boolean = IsNegative<B>> =
[_AIsNegative & _BIsNegative] extends [never] ?
//一正一负
([0] extends [A & B] ? Comparison.Equal : //-0==0
_AIsNegative extends true ? Comparison.Lower : Comparison.Greater) //-X<Y
:
//正负相同
(Length<AbsString<A>> extends Length<AbsString<B>> ?
//位数相同,从高位开始比较
(`${A}${B}` extends `` ? Comparison.Equal : //直到全部位都相同 return 相同
(High<A> extends High<B> ?
Comparator<DigitLowerRest<A>, DigitLowerRest<B>, _AIsNegative, _BIsNegative> : //当前位相同,比较更低位
DigitComparator<High<A>, High<B>, _AIsNegative>) //当前位不同,retrun
)
:
//位数不同,比较位数大的
Comparator<Length<AbsString<A>>, Length<AbsString<B>>, _AIsNegative, _BIsNegative>);
}
/**最大遍历深度 */
type TS_RECURSION_DEPTH_MAX = 999;
type Last<T extends any[]> = T extends [...any[], infer L] ? L : undefined;
type Concat<A1 extends any[], A2 extends any[]> = [...A1, ...A2];
type InclusiveRange<Lower extends number | bigint, Higher extends number | bigint,
_Result extends any[] = [],
_Next = _Result extends [] ? Lower : Last<_Result> extends number ? Adder.AddOne<Last<_Result>> : Lower> =
Comparator.Comparator<Lower, Higher> extends Comparator.Comparison.Greater ? []/*Lower > Hight*/ :
(_Next extends Higher ?
[..._Result, _Next] : //return
(_Result[`length`] extends TS_RECURSION_DEPTH_MAX ?
Concat<_Result, InclusiveRange<_Next extends number | bigint ? _Next : never, Higher>> : //optional: 每一次最大深度集合成一个数组并连接起来,使其支持更长的数组
InclusiveRange<Lower, Higher, [..._Result, _Next]>)); //[..., +1]
type test_large_number_support = InclusiveRange<31232456345634, 31232456345642>;
// type test_too_long_pass = InclusiveRange<0, 5000>;
Solution by E-uler #25682
// your answers
type Tuple<T extends number, TP extends number[] = []> =
TP['length'] extends T
? TP
: Tuple<T, [...TP, TP['length']]>
type InclusiveRange<Lower extends number, Higher extends number> =
Tuple<Higher> extends [...Tuple<Lower>, ...infer Rest]
? [...Rest, Higher]
: []
Solution by jxhhdx #24117
type InclusiveRange<
Lower extends number,
Higher extends number,
M extends number[] = [],
N extends number[] = []
> = Lower extends Higher
? [Higher]
: Higher extends M['length']
? [...M,Higher] extends [...N, ...infer Rest]
? N extends []
? []
: Rest
: []
: InclusiveRange<
Lower,Higher,
[...M,M['length']],
Lower extends M['length'] ? M : N['length'] extends 0 ? [] : N
>
Solution by TKBnice #23932
type InclusiveRange<
Lower extends number,
Higher extends number,
Index extends number[] = [],
R extends number[] = [],
> =
Higher extends Lower
? [Higher]
: Index['length'] extends Lower
? InclusiveRange<Lower, Higher, [...Index, 0], [...R, Index['length']]>
: Index['length'] extends Higher
? R['length'] extends 0
? []
: [...R, Higher]
: R['length'] extends 0
? InclusiveRange<Lower, Higher, [...Index, 0], R>
: InclusiveRange<Lower, Higher, [...Index, 0], [...R, Index['length']]>
Solution by drylint #23354
type Tuple<T extends number, TP extends number[] = []> =
TP['length'] extends T
? TP
: Tuple<T, [...TP, TP['length']]>
type InclusiveRange<Lower extends number, Higher extends number> =
Tuple<Higher> extends [...Tuple<Lower>, ...infer Rest]
? [...Rest, Higher] // include `Higher` as challenge requires us to do
: []
Well, after practices of previous challenges, this could be an easy one.
Solution by zhaoyao91 #22984
type CompareLen<A extends string, B extends string> = `${A}|${B}` extends `${string}${infer A}|${string}${infer B}` ? A extends "" ? B extends "" ? 0 : -1 : B extends "" ? 1 : CompareLen<A, B> : never;
type CompareDigit<A extends string, B extends string> = A extends B ? 0 : '0123456789' extends `${string}${A}${string}${B}${string}` ? -1 : 1;
type Compare<A extends string, B extends string, Len = CompareLen<A, B>> =
Len extends 0
? `${A}|${B}` extends `${infer AF}${infer AR}|${infer BF}${infer BR}`
? CompareDigit<AF, BF> extends infer N
? N extends 0
? `${AR}${BR}` extends "" ? 0 : Compare<AR, BR>
: N
: never
: never
: Len;
type UpToN<N extends number, C extends 0[] = []> = C['length'] extends N ? C : UpToN<N, [...C, 0]>;
type InclusiveRange<
Lower extends number,
Higher extends number,
E = Compare<`${Lower}`,`${Higher}`>,
C extends 0[] = UpToN<Lower>,
Res extends number[] = []> =
E extends 1 ? [] : E extends 0 ? [Lower] :
C['length'] extends Higher
? [...Res, C['length']]
: InclusiveRange<Lower, Higher, E, [...C, 0], [...Res, C['length']]>;
type test = InclusiveRange<1, 1000>;
Solution by BulatDashiev #17047
// your answers
type NumberToTuple<T extends number, Result extends 0[] = []> = Result['length'] extends T
? Result
: NumberToTuple<T, [0, ...Result]>
type MinusOne<T extends number, Result extends 0[] = NumberToTuple<T>> = Result extends [infer F, ...infer R]
? R['length']
: 0
type PlusOne<T extends number, Result extends 0[] = NumberToTuple<T>> = [...Result, 0]['length'] & number
type GT<A extends number, B extends number> = A extends B
? false
: A extends 0
? false
: B extends 0
? true
: GT<MinusOne<A>, MinusOne<B>>
type InclusiveRange<
Lower extends number,
Higher extends number,
Result extends number[] = []
> = GT<Lower, Higher> extends true
? Result
: InclusiveRange<PlusOne<Lower>, Higher, [...Result, Lower]>
Solution by humandetail #16692
// your answers
type Dictionary<
E extends any = any> =
{
'0':[],
'1':[E],
'2':[E,E],
'3':[E,E,E],
'4':[E,E,E,E],
'5':[E,E,E,E,E],
'6':[E,E,E,E,E,E],
'7':[E,E,E,E,E,E,E],
'8':[E,E,E,E,E,E,E,E],
'9':[E,E,E,E,E,E,E,E,E],
} ;
type _10<
E extends any = any> =[E,E,E,E,E,E,E,E,E,E] ;
type Multiply<
A extends readonly any[],
B extends readonly any[] > =
A extends [infer R,...infer U extends readonly any[]]
? [...B,...Multiply<U,B>]
: [] ;
type ReverseString<
Str extends string> =
Str extends `${infer R extends string}${infer U extends string}`
? `${ReverseString<U>}${R}`
: '' ;
type ReverseStringToTuple<
Str extends string> =
Str extends `${infer R extends keyof Dictionary}${infer U extends string}`
? [...Dictionary[R],...Multiply<_10,ReverseStringToTuple<U>>]
: [] ;
type InclusiveRange<
Lower extends number,
Higher extends number,
LowerTuple extends readonly any[] =
ReverseStringToTuple<ReverseString<`${Lower}`>>,
HigherTuple extends readonly any[] =
ReverseStringToTuple<ReverseString<`${Higher}`>>,
Range extends readonly any[] = [] > =
HigherTuple extends readonly [...LowerTuple,...readonly any[]]
? HigherTuple extends [infer R, ...infer U extends readonly any[]]
? InclusiveRange<Lower,U['length'],LowerTuple,U,[HigherTuple['length'],...Range]>
: [0,...Range]
: Range ;
Solution by justBadProgrammer #16658
// your answers
type ArrayByLength<T extends number, R extends any[] = []> =
T extends -1
? []
: R['length'] extends T
? R
: ArrayByLength<T, [...R, any]>
type PlusOne<T> =
T extends number
? [any, ...ArrayByLength<T>]['length']
: never;
type MinusOne<T> =
T extends number
? ArrayByLength<T> extends [infer F, ...infer R]
? R['length']
: -1
: never;
type LessThan<T extends number, U extends number> =
T extends 0
? U extends 0
? false
: U extends -1
? false
: true
: LessThan<MinusOne<T>, MinusOne<U>>
type SubstractArray<T extends number, U extends number, Count extends number = PlusOne<U>> =
T extends 0
? ArrayByLength<Count>
: SubstractArray<MinusOne<T>, U, MinusOne<Count>>
type InclusiveRange<Lower extends number, Higher extends number, Result extends number[] = []> =
LessThan<Higher, Lower> extends true
? Result
: SubstractArray<Lower, Higher> extends [infer F, ...infer R]
? InclusiveRange<PlusOne<Lower>, Higher, [...Result, Lower]>
: Result
Solution by mook2-y2 #16471
Starting with TypeScript 4.5, the compiler is performing Tail-Recursion Elimination on Conditional Types and the task can be solved much easier. Most of the published solutions rely on this feature that has introduced after the problem had been published
Solution with Tail-Recursion Elimination - works with TypeScript 4.5+
type InclusiveRange<
Lower extends number,
Higher extends number,
Res extends number[] = [],
Padding extends 0[] = [],
Current extends number = [...Padding, ...Res]['length'] & number
>
= Current extends Higher
? Current extends Lower
? [Current]
: Res extends []
? []
: [...Res, Current]
: Current extends Lower
? InclusiveRange<Lower, Higher, [Current], Padding>
: Res extends []
? InclusiveRange<Lower, Higher, [], [...Padding, 0]>
: InclusiveRange<Lower, Higher, [...Res, Current], Padding>
Solution without Tail-Recursion Elimination - works with TypeScript v4.4.4
type InclusiveRange<
Lower extends number,
Higher extends number,
All extends number[] = [],
Res extends number[] = [],
Next extends number[] = GetNext6<All>,
End extends number[] = LeftOf<Next, Higher>
>
= End extends []
? Res extends []
? InclusiveRange<Lower, Higher, [...All, ...Next], RightOf<Next, Lower>>
: InclusiveRange<Lower, Higher, [...All, ...Next], [...Res, ...Next]>
: Res extends []
? RightOf<End, Lower>
: [...Res, ...End]
// <[1, 2, 3, 4, 5], 3> -> [1, 2, 3]; <[1, 2, 3], 0> -> []; <[1, 2, 3], 5> -> []
type LeftOf<A, N> = A extends [...infer L, infer R] ? N extends R ? A : LeftOf<L, N> : []
// <[1, 2, 3, 4, 5], 3> -> [3, 4, 5]; <[1, 2, 3], 0> -> []; <[1, 2, 3], 5> -> []
type RightOf<A, N> = A extends [infer L, ...infer R] ? N extends L ? A : RightOf<R, N> : []
// <[0, 1, 2, 3, 4, 5]> -> [6, 7, 8, 9, 10, 11]
type GetNext6<A extends number[]> = [
[...A]['length'] & number,
[...A, 0]['length'] & number,
[...A, 0, 0]['length'] & number,
[...A, 0, 0, 0]['length'] & number,
[...A, 0, 0, 0, 0]['length'] & number,
[...A, 0, 0, 0, 0, 0]['length'] & number,
];
Solution by Alexsey #11625
type InclusiveRange<Lower extends number, Higher extends number, Result extends number[] = []>
= GreaterThan<Higher, Lower> extends true
? InclusiveRange<PlusOne<Lower>, Higher, [...Result, Lower]>
: Lower extends Higher
? [...Result, Lower]
: Result
type PlusOne<S extends number, Result extends string = '', Digits extends number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>
= `${S}` extends `${infer Lead extends number}9` ? PlusOne<Lead, `0${Result}`>
: {[Digit in keyof Digits & `${number}`]: `${S}` extends `${infer Lead}${Digit}`
? `${Lead}${Digits[Digit]}${Result}` extends `${infer Num extends number}` ? Num : never : never
}[keyof Digits & `${number}`]
type GreaterThan<N1 extends number, N2 extends number, P extends string = ``, Gt = undefined>
= `${N1}>${N2}` extends `${P}${infer D1}${any}>${P}${infer D2}${any}` ? Gt extends true | false ? GreaterThan<N1, N2, `${P}${any}`, Gt>
: D1 extends D2 ? GreaterThan<N1, N2, `${P}${any}`, Gt>
: GreaterThan<N1, N2, `${P}${any}`, '9876543210' extends `${any}${D1}${any}${D2}${any}` ? true : false>
: `${N1}` extends `${P}${any}${any}` ? true
: `${N2}` extends `${P}${any}${any}` ? false
: Gt extends true ? true : false
Solution by teamchong #11484
type Numberic = string | number
type ToTuple<A extends Numberic, R extends any[] = []> = `${A}` extends `${R['length']}`
? R : ToTuple<A, [...R, 1]>
type GreaterThan<A extends any[], B extends any[]> = A extends [... B, ... infer _] ? true : false
type InclusiveRangeTuple<A extends any[], B extends any[]> =
A extends [...B, infer _]
? []
: B extends [1, 1, 1, 1, 1, ...A, ... infer _]
? [
A['length'],
[...A, 1]['length'],
[...A, 1, 1]['length'],
[...A, 1, 1, 1]['length'],
[...A, 1, 1, 1, 1]['length'],
...InclusiveRangeTuple<[...A, 1, 1, 1, 1, 1], B>
]
: [A['length'], ...InclusiveRangeTuple<[...A, 1], B>]
type InclusiveRange<A extends number, B extends number> = GreaterThan<ToTuple<A>, ToTuple<B>> extends false
? InclusiveRangeTuple<ToTuple<A>, ToTuple<B>>
: A extends B ? [A] : []
Solution by ch3cknull #8055
We can use Tail-Recursion Elimination on Conditional Types.
// your answers
type InclusiveRange<Lower extends number,Higher extends number, C extends any[] = [], I = false, R extends number[] = []> =
I extends true ?
C["length"] extends Higher ?
[...R, Higher] :
InclusiveRange<Lower, Higher, [...C, 1], true, [...R, C["length"]]> :
C["length"] extends Lower ?
InclusiveRange<Lower, Higher, C, true> :
C["length"] extends Higher ?
[] :
InclusiveRange<Lower, Higher, [...C, 1], false>;
Solution by wotsushi #6111
type numToTuple<
T extends number | string,
Res extends unknown[] = []
> = `${T}` extends `${Res["length"]}` ? Res : numToTuple<T, [0, ...Res]>;
type isSmallOrEq<L extends number, R extends number> = numToTuple<R> extends [
...numToTuple<L>,
...infer _
]
? true
: false;
type sumOne<T extends unknown[]> = [...T, 0]["length"] extends number
? [...T, 0]["length"]
: never;
type InclusiveRange<
Lower extends number,
Higher extends number,
curIndex extends unknown[] = [],
res extends number[] = []
> = isSmallOrEq<Lower, Higher> extends true
? curIndex["length"] extends Higher
? [...res, Higher]
: curIndex["length"] extends Lower
? InclusiveRange<
sumOne<curIndex>,
Higher,
[0, ...curIndex],
[...res, Lower]
>
: InclusiveRange<Lower, Higher, [0, ...curIndex], res>
: [];
Solution by baian1 #6075
type N1 = [any];
type N2 = [any, any];
type N3 = [any, any, any];
type N4 = [any, any, any, any];
type N5 = [any, any, any, any, any];
type N6 = [any, any, any, any, any, any];
type N7 = [any, any, any, any, any, any, any];
type N8 = [any, any, any, any, any, any, any, any];
type N9 = [any, any, any, any, any, any, any, any, any];
type N10 = [any, any, any, any, any, any, any, any, any, any];
type DigitNumToTuple<N, L = N extends string | number ? `${N}` : ''> =
L extends `${N1['length']}`
? N1 : L extends `${N2['length']}`
? N2 : L extends `${N3['length']}`
? N3 : L extends `${N4['length']}`
? N4 : L extends `${N5['length']}`
? N5 : L extends `${N6['length']}`
? N6 : L extends `${N7['length']}`
? N7 : L extends `${N8['length']}`
? N8 : L extends `${N9['length']}`
? N9 : L extends `${N10['length']}`
? N10 : [];
type AddTen<T extends any[]> = [[...T, ...N1]['length'],
[...T, ...N2]['length'],
[...T, ...N3]['length'],
[...T, ...N4]['length'],
[...T, ...N5]['length'],
[...T, ...N6]['length'],
[...T, ...N7]['length'],
[...T, ...N8]['length'],
[...T, ...N9]['length'],
[...T, ...N10]['length']
];
type CumulativeTuple<T extends any[], L extends any[]> = L extends [...N10, ...infer O] ? [...AddTen<T>, ...CumulativeTuple<[...T, ...N10], O>] :
L extends N9 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length'], [...T, ...N5]['length'], [...T, ...N6]['length'], [...T, ...N7]['length'], [...T, ...N8]['length'], [...T, ...N9]['length']] :
L extends N8 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length'], [...T, ...N5]['length'], [...T, ...N6]['length'], [...T, ...N7]['length'], [...T, ...N8]['length']] :
L extends N7 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length'], [...T, ...N5]['length'], [...T, ...N6]['length'], [...T, ...N7]['length']] :
L extends N6 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length'], [...T, ...N5]['length'], [...T, ...N6]['length']] :
L extends N5 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length'], [...T, ...N5]['length']] :
L extends N4 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length'], [...T, ...N4]['length']] :
L extends N3 ? [[...T, ...N1]['length'], [...T, ...N2]['length'], [...T, ...N3]['length']] :
L extends N2 ? [[...T, ...N1]['length'], [...T, ...N2]['length']] :
L extends N1 ? [[...T, ...N1]['length']] : [];
// tuple repeat: [1], 3 => [1,1,1]
type TupleRepeat<T extends any[], N extends any, L extends any[] = [any], NS = N extends string | number ? `${N}` : ''> = NS extends '0'
? [] : `${L['length']}` extends NS
? T : [...T, ...TupleRepeat<T, N, [...L, any]>];
// number to char tuple: 123 => ['1','2','3']
type NumToCharTuple<N extends number, S extends string = `${N}`> = S extends '' ? [] : S extends `${infer F}${infer O}` ? [F, ...NumToCharTuple<N, O>] : [];
// generate length tuple
type GetLenTuple<Len extends number, LT extends any[] = NumToCharTuple<Len>, B extends any[] = [any]> = LT extends [...infer O, infer F] ? [...TupleRepeat<B, F>, ...GetLenTuple<Len, O, TupleRepeat<B, 10>>] : []
// get number length
type GetNumLen<N extends number, S extends string = `${N}`, R extends any[] = []> = S extends `${string}${infer O}` ? GetNumLen<N, O, [...R, any]> : R['length'];
type GetTupleDiff<L extends any[], R extends any[]> = L extends [...R, ...infer O] ? O : R extends [...L, ...infer O] ? O : [];
type TupleLenComparator<L extends any[], R extends any[]> = L extends [...R, ...infer O] ? O['length'] extends 0 ? 0 : 1 : -1;
type TupleAddRangeTuple<T extends any[], H extends any[], L extends any[] = GetTupleDiff<T, H>> = CumulativeTuple<T, L>;
type InclusiveRange<Lower extends number, Higher extends number> = Lower extends Higher ? [Lower] :
TupleLenComparator<DigitNumToTuple<GetNumLen<Lower>>, DigitNumToTuple<GetNumLen<Higher>>> extends 1 ? [] :
[Lower, ...TupleAddRangeTuple<GetLenTuple<Lower>, GetLenTuple<Higher>>];
Solution by venusliang #4794
type Tuple = Array<0>;
type Range = number[];
type Step = [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
];
/**
* Tail<[0, 0]> = [0].
* Tail<[]> = [].
*/
type Tail<T extends Tuple> = T extends [unknown, ...infer Rest] ? Rest : [];
type Next = { current: Tuple; added: Range };
type LowerAndHigher = { lower: Tuple; higher: Tuple };
type UntypedDoStep<
Current extends Tuple,
Limit extends number,
Rest extends Tuple = Step,
Added extends Range = []
> = Rest extends []
? { current: Current; added: Added }
: Current['length'] extends Limit
? { current: Current; added: Added }
: UntypedDoStep<[0, ...Current], Limit, Tail<Rest>, [...Added, Current['length']]>;
/**
* DoStep<[], 4> = { current: [0, 0, 0, 0], added: [0, 1, 2, 3] }.
*/
type DoStep<
Current extends Tuple,
Limit extends number,
N = UntypedDoStep<Current, Limit>
> = N extends Next ? N : never;
type UntypedLowerTuples<
Lower extends number,
Higher extends number,
L extends Tuple = [],
H extends Tuple = []
> = L['length'] extends Lower
? { lower: L; higher: H }
: H['length'] extends Higher
? { lower: L; higher: H }
: UntypedLowerTuples<Lower, Higher, DoStep<L, Lower>['current'], DoStep<H, Higher>['current']>;
/**
* LowerTuples<3, 4> = { lower: [0, 0, 0], higher: [0, 0, 0, 0] }.
*/
type LowerTuples<
Lower extends number,
Higher extends number,
R = UntypedLowerTuples<Lower, Higher>
> = R extends LowerAndHigher ? R : never;
/**
* GreaterOrEqual<[0, 0], [0, 0]> = true.
* GreaterOrEqual<[0, 0], [0, 0, 0]> = false.
* GreaterOrEqual<[0, 0], [0]> = true.
* GreaterOrEqual<[], [0]> = false.
*/
type GreaterOrEqual<X extends Tuple, Y extends Tuple> = X extends [...Y, ...Tuple] ? true : false;
/**
* RangeFrom<[], 5> = [0, 1, 2, 3, 4, 5].
* RangeFrom<[0, 0], 6> = [2, 3, 4, 5, 6].
*/
type RangeFrom<
T extends Tuple,
Higher extends number,
R extends Range = [],
S extends Next = DoStep<T, Higher>
> = T['length'] extends Higher
? [...R, T['length']]
: RangeFrom<S['current'], Higher, [...R, ...S['added']]>;
type InclusiveRange<
Lower extends number,
Higher extends number,
Tuples extends LowerAndHigher = LowerTuples<Lower, Higher>
> = GreaterOrEqual<Tuples['higher'], Tuples['lower']> extends false
? []
: RangeFrom<Tuples['lower'], Higher>;
Solution by uid11 #826