04425-medium-greater-than

Back

type StringToArray<T extends string> = T extends `${infer L extends number}${infer Rest}` ? [L, ...StringToArray<Rest>] : []
type CreateArrayByNumber<T extends number, R extends any[] = []> = R['length'] extends T ? R : CreateArrayByNumber<T, [...R, undefined]>
type CompareOneDigit<T extends number, U extends number> = T extends U ? false :  CreateArrayByNumber<T> extends [...CreateArrayByNumber<U>, ...infer _] ? true : false
type CompareAllNumber<T extends any[], U extends any[], CompareCount extends any[] = []> = T['length'] extends U['length'] ? CompareCount['length'] extends T['length'] ? false : CompareOneDigit<T[CompareCount['length']], U[CompareCount['length']]> extends true ? true : CompareAllNumber<T, U, [...CompareCount, 1]> : T[U['length']] extends undefined ? false : true
type GreaterThan<T extends number, U extends number> = CompareAllNumber<StringToArray<`${T}`>, StringToArray<`${U}`>>

Solution by devshinthant #35270

type Unshift<T extends any[]> = T extends [any, ...infer R] ? R : [];

// * 114514 => [1, 1, 4, 5, 1, 4]
type NumberToArray<
  T extends number,
  S = `${T}`
> = S extends `${infer F extends number}${infer R}`
  ? [F, ...NumberToArray<0, R>]
  : [];

// * 5 => 0 | 1 | 2 | 3 | 4 | 5
type NumberIncreseUnion<
  T extends number,
  D extends any[] = []
> = D["length"] extends T ? T : D["length"] | NumberIncreseUnion<T, [0, ...D]>;

// * <[1, 2, 3], [1, 2, 3]> => false
type SameLengthGreaterThen<T extends any[], U extends any[]> = T extends []
  ? never
  : SingleGreaterThan<T[0], U[0]> extends never
  ? // *  T ≤ U
    SingleGreaterThan<U[0], T[0]> extends never
    ? // * & T ≥ => T == U, continue last
      SameLengthGreaterThen<Unshift<T>, Unshift<U>>
    : // * T < U => never
      never
  : // * T > U => true
    true;

// * T, U ∈ [0, 9]
// * <4, 5> => never <5, 5> => never <5, 4> => true
type SingleGreaterThan<
  T extends number,
  U extends number,
  T2U extends number = NumberIncreseUnion<T>,
  U2U extends number = NumberIncreseUnion<U>
> = Exclude<T2U, U2U> extends never ? never : true;

type GreaterThan<
  T extends number,
  U extends number,
  TA extends number[] = NumberToArray<T>,
  UA extends number[] = NumberToArray<U>
> = (
  TA["length"] extends UA["length"]
    ? SameLengthGreaterThen<TA, UA>
    :  SingleGreaterThan<TA["length"], UA["length"]>
) extends never
  ? false
  : true;

Solution by cccPumpk1nn #35019

从第一位开始比较并存储比较结果,直到比较完其中一个数所有数字为止。 存储规则为:T > U 为 true,T < U 为 false,T = U 为 0 若 T 先被扫描完,扫描结果数组中第一个非 0 值(true或者false)就是比较结果,如果全为 0 也是 false。

type ThanOne<T extends number, U extends number, R extends any[] = []> = T extends U ? 0 : R['length'] extends T ? false : R['length'] extends U ? true : ThanOne<T, U, [...R, any]>
type Helper<T extends unknown[]> = T extends [infer First, ...infer Rest] ? First extends 0 ? Helper<Rest> : First : false
type GreaterThan<T extends number | string, U extends number | string, R extends any[] = []> = [`${T}`, `${U}`] extends [`${infer First1 extends number}${infer Rest1}`, `${infer First2 extends number}${infer Rest2}`]
  ? GreaterThan<Rest1, Rest2, [...R, ThanOne<First1, First2>]>
  : T extends '' ? Helper<R> : true

Solution by 2083335157 #34919

// digit comparison: GT<'4', '2'> = true, GT<'2', '4'> = false, GT<'3', '3'> = undefined
type GT<A extends string, B extends string> =
 A extends B ? undefined :
 '9876543210' extends `${string}${A}${string}${B}${string}` ? true : false;

// 1. the number with more digits is greater
// 2. if numbers have the same length, use the first different digit to tell which number is greater
//    B remembers which number had the first greater digit, not used unless numbers turn out to be of the same length
type GreaterThan<T extends number | string, U extends number | string, B extends boolean | undefined = undefined> = 
  T extends U ? B extends boolean ? B : false :
  `${T}` extends `${infer T1}${infer TR}` ?
    `${U}` extends `${infer U1}${infer UR}` ?
       GreaterThan<TR, UR, B extends boolean ? B : GT<T1, U1>>
       : true
    : false;

Solution by cipak #34620

// convert string into number
// eg.
// StringToNum<"123"> -> 123
type StringToNum<S extends string> = S extends `${infer N extends number}` ? N : never;

// split number to tuple of digits
// eg.
// NumToDigitsTuple<"123"> -> ["1", "2", "3"]
type NumToDigitsTuple<N extends string> = N extends `${infer L}${infer R}` ? [L, ...NumToDigitsTuple<R>] : [];

// produce tuple of length N by adding elements (type U) to original tuple T
// eg.
// Fill<["1", "2"], "0", 5> -> ["0", "0", "0", "1", "2"]
type Fill<T extends string[], U extends string, N extends number> = T["length"] extends N ? T : Fill<[U, ...T], U, N>;

// produce tuple of length N
// eg.
// NumToZeroTuple<3> -> [0, 0, 0]
type NumToZeroTuple<N extends number, T extends unknown[] = []> = T["length"] extends N
  ? T
  : NumToZeroTuple<N, [...T, 0]>;

// compare length of two tuples
// eg.
// CompareByTupleLength<[0, 0], [0]> -> true
// CompareByTupleLength<[0], [0, 0]> -> false
// CompareByTupleLength<[0], [0]> -> false
type CompareTupleLength<T extends unknown[], U extends unknown[]> = T["length"] extends U["length"]
  ? false
  : T extends [unknown, ...infer TRest]
  ? U extends [unknown, ...infer URest]
    ? CompareTupleLength<TRest, URest>
    : true
  : false;

// eg.
// CompareDigitsTuple<["1", "2"], ["1", "1"]> -> true
// CompareDigitsTuple<["1", "2"], ["1", "3"]> -> false
// CompareDigitsTuple<["1", "2"], ["1", "2"]> -> false
type CompareDigitsTuple<T extends string[], U extends string[]> = T extends [
  infer TFirst extends string,
  ...infer TRest extends string[]
]
  ? U extends [infer UFirst extends string, ...infer URest extends string[]]
    ? TFirst extends UFirst
      ? CompareDigitsTuple<TRest, URest>
      : CompareTupleLength<NumToZeroTuple<StringToNum<TFirst>>, NumToZeroTuple<StringToNum<UFirst>>>
    : never
  : false;

type GreaterThan<T extends number, U extends number> = CompareDigitsTuple<
  Fill<NumToDigitsTuple<`${T}`>, "0", 15>,
  Fill<NumToDigitsTuple<`${U}`>, "0", 15>
>;

Solution by yukicountry #34411

  1. Convert T\U number to array
  2. Compare by the length of the array
  3. If the length of the array is the same, compare by digit
type NumToCharArr<T extends number | string> = `${T}` extends `${infer F extends number}${infer R}` ? [...NumToCharArr<R>, F] : []

// If the length of A is greater than the length of B, then A[B['length']] should not be undefined.
type CompareLen<
    A extends number,
    B extends number,
    AA extends number[] = NumToCharArr<A>,
    BA extends number[] = NumToCharArr<B>,
> = AA[BA['length']] extends undefined
    ? BA[AA['length']] extends undefined
        ? never
        : false
    : true

type NumToArr<T extends number, A extends number[] = []> = A['length'] extends T
    ? A
    : NumToArr<T, [...A, 1]>

type CompareByDigits<
    A extends number,
    B extends number,
    AA extends number[] = NumToCharArr<A>,
    BA extends number[] = NumToCharArr<B>,
> = AA extends [infer AF extends number, ...infer AR extends number[]]
    ? BA extends [infer BF extends number, ...infer BR extends number[]]
        ? [CompareLen<AF, BF, NumToArr<AF>, NumToArr<BF>>] extends [never]
            ? CompareByDigits<A, B, AR, BR>
            : CompareLen<AF, BF, NumToArr<AF>, NumToArr<BF>>
        : true
    : BA extends [infer _, ...infer _]
        ? false
        : false


type GreaterThan<T extends number, U extends number, LC extends any = CompareLen<T, U>> = [LC] extends [never] ? CompareByDigits<T, U> : LC

Solution by MAXLZ1 #34263

// your answers

type ToNumberList<
  N extends string,
  S extends string = `${N}`
> = S extends `${infer F extends number}${infer R}`
  ? [F, ...ToNumberList<R>]
  : [];

type FillZero<N extends number, L extends number[], _L = L, MAX = 20> = L["length"] extends N
  ? L
  : L["length"] extends MAX ? _L : FillZero<N, [0, ...L], _L>;

type FormatNumberList<T extends number[], Len extends number> = FillZero<
  Len,
  T
>;


type UnShift<T extends number[]> = T extends [infer F, ...infer R] ? R : never;

type GreaterThanNumber<
  A extends number,
  B extends number,
  L extends number[] = []
> = L["length"] extends A
  ? false
  : L["length"] extends B
  ? true
  : GreaterThanNumber<A, B, [0, ...L]>;

type GreaterThan<
  A extends number,
  B extends number,
  AL extends number[] = ToNumberList<`${A}`>,
  BL extends number[] = ToNumberList<`${B}`>,
  FAL extends number[] = FormatNumberList<AL, BL["length"]>,
  FBL extends number[] = FormatNumberList<BL, AL["length"]>
> = FAL extends []
  ? false
  : FBL extends []
  ? true
  : FAL[0] extends FBL[0]
  ? GreaterThan<A, B, AL, BL, UnShift<FAL>, UnShift<FBL>>
  : GreaterThanNumber<FAL[0], FBL[0]>;

TOO COMPLEX!!


Solution by chenqy-yh #34214

// 过不了大数
type GreaterThan<T extends number, U extends number, C extends any[] = []> = C['length'] extends T ? false
: C['length'] extends U ? true : GreaterThan<T, U, [...C, 1]>

Solution by ouzexi #34070

// your answers
// 将数字转为字符串 17 -> '17'
type NumberToString<T extends number> = `${T}`

// 将字符串转为数组 '17' -> ['1', '7']
type StringToArray<T extends string, Res extends any[] = []> = T extends `${infer A}${infer R}` ? 
  StringToArray<R, [...Res, A]> : Res

// 将数字转为数字对应长度的数组 3 -> [null, null, null]
type DigitToArray<T extends number, Res extends any[] = []> = T extends Res['length'] ? Res 
  : DigitToArray<T, [...Res, null]>

// 如 17,转为字符串的长度为2,转为[null, null]
type NumberToArray<T extends number> = DigitToArray<StringToArray<NumberToString<T>>['length']>

// 字符串数组转数字数组
type StringArrayToNumberArray<T extends any[], Res extends any[] = []> = T extends [infer A, ...infer R] 
  ? StringArrayToNumberArray<R, [...Res, A extends `${infer X extends number}` ? X : A]>: Res

// 两个数组长度比较,等于返回0 ,大于返回1,小于返回-1
type Compare<A extends any[], B extends any[]> = A['length'] extends B ['length'] ? 0 
  : A extends [...B, ...infer _] ? 1 : -1

// 先比较两个数字的长度,若长度相同,再从第一位开始逐位比较
type GreaterWholeLength<T extends number, U extends number> = Compare<NumberToArray<T>, NumberToArray<U>>
type GreaterOneByOne<T extends any[], F extends any[]> = T extends [infer A extends number, ...infer R] ? 
  F extends [infer X extends number, ...infer Y] ? 
    Compare<DigitToArray<A>, DigitToArray<X>> extends 1 ? true : GreaterOneByOne<R, Y>
    : false 
  : false

type GreaterThan<T extends number, U extends number> = GreaterWholeLength<T, U> extends 1 ? true 
  : GreaterOneByOne<StringArrayToNumberArray<StringToArray<NumberToString<T>>>, StringArrayToNumberArray<StringToArray<NumberToString<U>>>>


Solution by heyuelan #33847

type Map = {
  "0": [];
  "1": ["0"];
  "2": ["1", "0"];
  "3": ["2", "1", "0"];
  "4": ["3", "2", "1", "0"];
  "5": ["4", "3", "2", "1", "0"];
  "6": ["5", "4", "3", "2", "1", "0"];
  "7": ["6", "5", "4", "3", "2", "1", "0"];
  "8": ["7", "6", "5", "4", "3", "2", "1", "0"];
  "9": ["8", "7", "6", "5", "4", "3", "2", "1", "0"];
};

type Includes<T, U> = T extends [infer F, ...infer R]
  ? Equal<F, U> extends true
    ? true
    : Includes<R, U>
  : false;

// A가 B보다 자릿수가 큰 숫자인지 확인하는 타입
type GreaterThanByStringLength<
  S1 extends string,
  S2 extends string
> = S1 extends `${string}${infer S1R}`
  ? S2 extends `${string}${infer S2R}`
    ? GreaterThanByStringLength<S1R, S2R>
    : true // A가 큰 경우
  : false; // 같거나, B가 큰 경우

type GreaterByDigit<
  S1 extends string,
  S2 extends string
> = S1 extends `${infer S1F extends keyof Map}${infer S1R}`
  ? S2 extends `${infer S2F}${infer S2R}`
    ? Includes<Map[S1F], S2F> extends true
      ? true
      : GreaterByDigit<S1R, S2R>
    : false
  : false;

type GreaterThan<N1 extends number, N2 extends number> = N1 extends N2
  ? false
  : GreaterThanByStringLength<`${N1}`, `${N2}`> extends true
  ? true // N1의 자릿수가 큰 경우
  : GreaterByDigit<`${N1}`, `${N2}`> extends true
  ? true // 자릿수가 같을 때, 각 자릿값을 비교해 N1이 큰 경우
  : false;

Solution by DoGukKim #33789

type GreaterThanDigit<T extends number, U extends number, Acc extends  readonly 1[] = []> = T extends Acc['length'] 
  ? false 
  : U extends Acc['length'] 
    ? true 
    : GreaterThanDigit<T, U, [1, ...Acc]>

type ToDigitTuple<T extends string> = `${T}` extends `${infer Head extends number}${infer Tail}` 
  ? [Head, ...ToDigitTuple<Tail>] 
  : [];

type CompareDigitTuples<T extends number[], U extends number[]> = GreaterThanDigit<T['length'], U['length']> extends false 
  ? T extends [infer THead extends number, ...infer TTail extends number[]] 
    ? U extends [infer UHead extends number, ...infer UTail extends number []] 
      ? THead extends UHead 
        ? CompareDigitTuples<TTail, UTail> 
        : GreaterThanDigit<THead, UHead> 
      : never
    : false
  : true

type GreaterThan<T extends number, U extends number> = CompareDigitTuples<ToDigitTuple<`${T}`>, ToDigitTuple<`${U}`>>

Solution by ruslauz #33761

type TupleFromNum<T, Arr extends string[] = []> = T extends `${Arr['length']}` ? Arr : TupleFromNum<T, [...Arr, '1']>


type CompareArr<T extends any[], U extends any[]> = T extends [infer FT, ...infer RT] 
  ? U extends [infer FU, ...infer RU] 
    ? FT extends FU
      ? CompareArr<RT, RU>
      : CompareArr<TupleFromNum<FT>, TupleFromNum<FU>>
    : true
  : false


type StringToArr<S1 extends string, S2 extends string, ArrS1 extends any[] = [], ArrS2 extends any[] = []> =
S1 extends `${infer FS1}${infer RS1}`
  ? S2 extends `${infer FS2}${infer RS2}`
    ? StringToArr<RS1, RS2, [...ArrS1, FS1], [...ArrS2, FS2]>
    : true
  : S1 extends ''
    ? S2 extends ''
      ? CompareArr<ArrS1, ArrS2> 
      : false 
    : never

type GreaterThan<T extends number, U extends number> = StringToArr<`${T}`, `${U}`> 

Solution by PiligrimStas #33735

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

// DigitFrom<'123'> -> [1, 2, 3]
type DigitFrom<T extends string, U extends number[] = []> = 
  `${T}` extends `${infer F extends number}${infer R}`
    ? DigitFrom<R, [...U, F]>
    : U

type DigitGreaterThan<T extends number[], U extends number[]> = 
  T extends [infer F1 extends number, ...infer R1 extends number[]] // 从高位开始比较
    ? U extends [infer F2 extends number, ...infer R2 extends number[]]
      ? Seq<F1> extends [...Seq<F2>, ...infer R] // F1 是否大于等于 F2
        ? R['length'] extends 0 // 如果F1 等于 F2,继续比较下一位
          ? DigitGreaterThan<R1, R2> 
          : true
        : false
      : never
    : false

type GreaterThan<T extends number, U extends number, TD extends number[] = DigitFrom<`${T}`>, UD extends number[] = DigitFrom<`${U}`>> = 
  TD['length'] extends UD['length'] // 位数是否相同
    ? DigitGreaterThan<TD, UD> // 相同则比较每一位之间的大小
    : GreaterThan<TD['length'], UD['length']> // 否则比较位数之间的大小
  1. 位数之间是否相同?
  2. 相同的话则比较每一位之间大小 1. 从高位开始比较,如果相同则继续比较下一位
  3. 不相同的话,比较位数大小(开始递归)

例如123789的比较步骤 123每一位为[1, 2, 3],位数为3 129每一位为[1, 2, 9],位数为3

  1. 3 == 3
  2. 1 == 1
  3. 2 == 2
  4. 3 < 9,结束,得到123 < 789

例如2^53-19007199254740991789的比较步骤 9007199254740991每一位为[9,0,0,7,1,9,9,2,5,4,7,4,0,9,9,1],位数为16 789每一位为[7, 8, 9],位数为3

  1. 16 != 3
  2. 2 != 1,比较16(位数为2)和3(位数为1)
  3. 1 == 1,比较2(位数为1)和1(位数为1)
  4. 2 > 1,结束,得到9007199254740991 > 789

Solution by hui0808 #33429

type GreaterThan<T extends number, U extends number, CountList extends number[] = []> = CountList['length'] extends T | U 
  ? CountList['length'] extends T ? false : true 
  : GreaterThan<T, U, [1, ...CountList]>;

Solution by ZhipengYang0605 #33405

There are a lot of additional processing, the main purpose is to split the big number into number[]


type NotZero = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type Num = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;

// specific number to specific length array, 3 => [1,1,1]   5=>[1,1,1,1,1]
// not avalible for big number
type NumberToArray<
  N extends number,
  Arr extends any[] = []
> = N extends Arr["length"] ? Arr : NumberToArray<N, [...Arr, 1]>;

//compare two number
type GreaterThanForSingleNumber<
  A extends number,
  B extends number
> = NumberToArray<A> extends [...NumberToArray<B>, ...infer _] ? true : false;

type RemoveArrFirst<T extends any[]> = T extends [infer _, ...infer Rest]
  ? Rest
  : never;

type GreaterThanForArr<
  T extends number[],
  U extends number[]
> = T["length"] extends U["length"]
  ? T[0] extends U[0]
    ? GreaterThanForArr<RemoveArrFirst<T>, RemoveArrFirst<U>>
    : GreaterThanForSingleNumber<T[0], U[0]>
  : GreaterThanForSingleNumber<T["length"], U["length"]>;

// number string to number array, '1234' => [1, 2, 3, 4]
type StringToArray<T extends string> = T extends ``
  ? []
  : `${T}` extends `${infer First extends Num}${infer Rest}`
  ? [First, ...StringToArray<Rest>]
  : never;

type GreaterThan<T extends number, U extends number> = T extends U
  ? false
  : GreaterThanForArr<StringToArray<`${T}`>, StringToArray<`${U}`>>;

Solution by sunupupup #33376

type ParseInt<T extends string> = T extends `${infer Digit extends number}`
  ? Digit
  : never;

type ReverseString<S extends string> = S extends `${infer First}${infer Rest}`
  ? `${ReverseString<Rest>}${First}`
  : "";

type RemoveLeadingZeros<S extends string> = S extends "0"
  ? S
  : S extends `${"0"}${infer R}`
  ? RemoveLeadingZeros<R>
  : S;

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 MinusOne<T extends number> = T extends 0
  ? -1
  : ParseInt<
      RemoveLeadingZeros<ReverseString<InternalMinusOne<ReverseString<`${T}`>>>>
    >;

type InnerGreaterThan<T extends number, U extends number> = T extends U ? true : (
  T extends 0 ? false : InnerGreaterThan<MinusOne<T>, U>
)

type GreaterThan<T extends number, U extends number> = T extends U ? false : (
  U extends 0 ? true : InnerGreaterThan<T, U>
)

Solution by vangie #32944

type InitArr<T extends number, Arr extends unknown[] = []> =
  Arr["length"] extends T ? Arr : InitArr<T, [...Arr, unknown]>
type SubTra<T extends number, K extends number> =
  InitArr<T> extends [...args: InitArr<K>, ...infer R] ? R['length'] : never;
type GreaterThan<T extends number, K extends number> =
  [SubTra<NumberToTuple<`${T}`>["length"], 4>] extends [never]
  ? SubTra<T, K> extends 0 ? false : true
  : BigNumGreaterThan<T, K> // 大于最大深度1000
type NumberToTuple<T extends string, Arr extends string[] = []> =
  T extends `${infer A}${infer B extends string}` ? NumberToTuple<B, [...Arr, A]> : Arr;
type BigNumGreaterThan<T extends number, K extends number> =
  [SubTra<NumberToTuple<`${T}`>["length"], NumberToTuple<`${K}`>["length"]>] extends [never]
  ? false // 如果T的长度比K的长,则T<K false
  : SubTra<NumberToTuple<`${T}`>["length"], NumberToTuple<`${K}`>["length"]> extends 0
    ? GreaterThanArr<NumberToTuple<`${T}`>,NumberToTuple<`${K}`>> // 长度一致,需要细致比较
    : true // T>K true
    type GreaterThanArr<T extends string[],K extends string[]> = 
    T extends [infer A extends string, ...infer B extends string[]]
    ? K extends [infer C extends string, ... infer D extends string[]]
      ? GreaterThan<StrToNum<A>,StrToNum<C>> extends true
        ? true
        : GreaterThanArr<B,D>
      : never
    :false;
  type StrToNum<T extends string> = T extends `${infer S extends number}`?S:never;

我的思路是:

思路比较繁琐,希望大佬给出更优解

Solution by I-am-a-king-of-vue #32186

type StringToArr<T extends string, Acc extends string[] = []> = 
    T extends `${infer Head}${infer Tail}` 
        ? StringToArr<Tail, [...Acc, Head]> 
        : Acc
;

type Shift<T extends unknown[]> = T extends [unknown, ...infer Tail] ? Tail : [];
type First<T extends string[]> = T extends [infer Head, ...unknown[]] ? Head : '';
type ToNumber<T extends string> = T extends `${infer A extends number}` ? A : never;

type GreaterThan<
    T extends number, 
    U extends number
> = GreaterThanInternal<StringToArr<`${T}`>, StringToArr<`${U}`>>;

type GreaterThanInternal<
    T extends string[], 
    U extends string[]
> = 
    T extends U 
        ? false 
        : T["length"] extends U["length"] 
            ? NumberGreaterThan<T, U> 
            : GreaterThan<T["length"], U["length"]>
;

type NumberGreaterThan<
    T extends string[], 
    U extends string[]
> = 
    First<T> extends First<U> 
        ? NumberGreaterThan<Shift<T>, Shift<U>> 
        : DigitGreaterThan<ToNumber<First<T>>, ToNumber<First<U>>>
;

type DigitGreaterThan< // compares dirrerent digits (you can replace this type with low performance solution of this challenge)
    T extends number, 
    U extends number
> = 
  T extends 0 
    ? false 
    : U extends 0 
      ? true 
      : T extends 1 
        ? false 
        : U extends 1 
          ? true 
          : T extends 2 
            ? false 
            : U extends 2 
              ? true 
              : T extends 3 
                ? false 
                : U extends 3 
                  ? true 
                  : T extends 4 
                    ? false 
                    : U extends 4 
                      ? true 
                      : T extends 5 
                        ? false 
                        : U extends 5 
                          ? true 
                          : T extends 6 
                            ? false 
                            : U extends 6 
                              ? true 
                              : T extends 7 
                                ? false 
                                : U extends 7 
                                  ? true 
                                  : T extends 8 
                                    ? false 
                                    : true
;

Solution by sdrjs #31658

// compare T & U 's length first. if they have different length, choose the lenger one; else compare them by digit
// 先比长度,长度不同选长度大的,长度相同按位比较
interface Greater {'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 GreaterThan<T extends number, U extends number> = 
  StringGreaterThan<`${T}`, `${U}`> extends boolean
    ? StringGreaterThan<`${T}`, `${U}`>
    : CompareByDigit<`${T}`, `${U}`>

type StringGreaterThan<T extends string, U extends string> = 
  T extends `${infer TFirst}${infer TRest}`
    ? U extends `${infer UFirst}${infer URest}`
      ? StringGreaterThan<TRest, URest>
      : true
    : U extends `${infer UFirst}${infer URest}`
      ? false
      : undefined

type CompareByDigit<T extends string, U extends String> = 
  T extends `${infer TFirst}${infer TRest}`
    ? U extends `${infer UFirst}${infer URest}`
      ? CompareDight<TFirst, UFirst> extends boolean
        ? CompareDight<TFirst, UFirst> 
        : CompareByDigit<TRest, URest>
      : undefined
    : false

type CompareDight<A extends string, B extends string> = 
  A extends B
    ? undefined
    : A extends keyof Greater 
        ? B extends Greater[A]
          ? true
          : false
        : undefined

Solution by GodAraden #31265

// 比较两个数字的大小
type ThanNum<T extends number, U extends number, O extends any[] = []> =  Equal<T, U> extends true 
? false 
: O['length'] extends T 
? false 
: O['length'] extends U 
? true 
: ThanNum<T, U, [...O, 1]>

// 将对比的值转为数组进行大小对比
type Str2Arr<T extends string, U extends any[] = []> = T extends `${infer A}${infer B}` ? Str2Arr<B, [...U, A]> : U

// 将两个长度相同的值的位数一位一位进行对比,相等则对比下一位
type ThanString<T extends string, U extends string> = T extends `${infer A extends number}${infer B}` 
? U extends `${infer C extends number}${infer D}` 
? ThanNum<A, C> extends true
? true 
: ThanString<B, D>
: false
: false

// 先对比两个数字的长度,更长的一定更大
type GreaterThanString<T extends string, U extends string> = ThanNum<Str2Arr<T>['length'], Str2Arr<U>['length']> extends true ? true : ThanString<T, U>

type GreaterThan<T extends number, U extends number> = GreaterThanString<`${T}`, `${U}`>

Solution by dreamluo-plus #30646

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

// 两数差值数组
type MinusArray<L extends number, M extends number, T extends number[] = NumberArray<L>, S extends number[] = NumberArray<M>, N extends 0[] = [], P extends 1[] = []> = 
  [...P, ...N]['length'] extends M
    ?
      T['length'] extends 0
        ? 
          N
        : T  
    : T extends [number, ...infer Rest extends number[]]
        ?
          MinusArray<L, M, Rest, S, N, [...P, 1]>
        : S['length'] extends L
          ?
            N
          : S extends [number, ...infer Rest extends number[]]
              ?
                MinusArray<L, M, T, Rest, [...N, 0], P>
              : never

// 计算两数差值
type Diff<T extends number, U extends number, M extends number[] = MinusArray<T, U>> = 
  M['length'] extends 0
    ?
      '0'
    : M[0] extends 0
      ?
        `-${M['length']}`
      : M[0] extends 1
          ? 
            `${M['length']}`
          : never

type StringToNumber<T extends string> =  T extends `${infer A extends number}` ? A : never

type StringToArray<T extends number, S extends string = `${T}`, R extends number[] = []> = 
  S extends `${infer A}${infer Rest}`
    ? 
      StringToArray<T, Rest, [...R, StringToNumber<A>]>
    : R

type CompatibleGreaterThan<T extends number, U extends number, F extends string = `${T}`, S extends string = `${U}`, L extends number[] = StringToArray<T>, M extends number[] = StringToArray<U>, D extends string = Diff<L['length'], M['length']>> =
  D extends '0'
    ? 
      F extends `${infer A}${infer B}`
        ?
          S extends `${infer C}${infer E}`
            ?
              Diff<StringToNumber<A>, StringToNumber<C>> extends '0'
                ? 
                  CompatibleGreaterThan<T, U, B, E>
                : Diff<StringToNumber<A>, StringToNumber<C>> extends `${infer A}${string}`
                    ? 
                      A extends '-'
                        ?
                          false
                        : true
                    : never
            : true
        : false
    : D extends `${infer H}${string}`
        ?
          H extends '-'
            ?
              false
            : true
        : never
                
type GreaterThan<T extends number, U extends number> = CompatibleGreaterThan<T, U>

Solution by zhangqiangzgz #30195

This solution converts both numbers to digit arrays. It then compares the length of these arrays. In case of different lengths, the comparison already determines the result. In case of arrays of equal length, leading equal digits in both arrays are skipped. The comparison of the first digit difference in the arrays determines the final result.

The same special comparison for small numbers is used for both the comparison of array lengths and array digits.

This solution also shows how to use infer with extends to infer array elements/rests in a way that they fulfill type constraints in (recursive) calls.

type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

type ToDigitArray<
  N extends number,
  S extends string = `${N}`
> =
  S extends `${infer D extends Digit}${infer R}`
    ? [D, ...ToDigitArray<0, R>]
    : []

type CompareSmallNumbers<
  M extends number,
  N extends number,
  C extends 0[] = [],
  L = C['length']
> =
  L extends M
    ? L extends N ? 0 : -1
    : L extends N ? 1 : CompareSmallNumbers<M, N, [...C, 0]>

type CompareEquallyLongDigitArrays<
  D extends Digit[],
  E extends Digit[],
  F extends Digit = D[0],
  G extends Digit = E[0],
  C = CompareSmallNumbers<F, G>
> =
  C extends -1 | 1 ? C :
  [D, E] extends [[F, ...infer R extends Digit[]], [G, ...infer S extends Digit[]]]
    ? [R, S] extends [[], []] ? 0 : CompareEquallyLongDigitArrays<R, S>
    : never

type GreaterThan<
  T extends number,
  U extends number,
  D extends Digit[] = ToDigitArray<T>,
  E extends Digit[] = ToDigitArray<U>,
  G = CompareSmallNumbers<D['length'], E['length']>
> =
  G extends 1 ? true :
  G extends -1 ? false :
  CompareEquallyLongDigitArrays<D, E> extends 1 ? true : false

Solution by sbr61 #30181

// 你的答案
type NTS<T extends number> = `${T}`
type STN<T extends string> = T extends `${infer F extends number}` ? F : never
type STA<T extends string> = T extends `${infer F}${infer R}` ? [STN<F>, ...STA<R>] : []

type GreaterThanArrL<T extends number, U extends number, R extends ''[] = []> =
  T extends R['length'] ? false : U extends R['length'] ? true : GreaterThanArrL<T, U, ['', ...R]>

type SameThanArr<T extends number[], U extends number[], R extends ''[] = []> =
  T[R['length']] extends number ?
  T[R['length']] extends U[R['length']] ? SameThanArr<T, U, ['', ...R]> :
  GreaterThanArrL<T[R['length']], U[R['length']]> : false

type GreaterThan<T extends number, U extends number, TL extends number[] = STA<NTS<T>>, UL extends number[] = STA<NTS<U>>> =
  TL['length'] extends UL['length'] ?
  SameThanArr<TL, UL>
  : GreaterThanArrL<TL['length'], UL['length']>

Solution by YE840926098 #30122

type GetSymbol<A extends string, B extends string, F extends any[] = []> =
  `${F['length']}` extends A
    ? `${F['length']}` extends B ? '=' : '<'
    : `${F['length']}` extends B ? '>' : GetSymbol<A, B, [...F, 1]>

type GreaterThan<T extends number | string, U extends number | string, S extends '>' | '<' | '=' = '='> =
  `${T}` extends `${infer A}${infer R1}`
    ? `${U}` extends `${infer B}${infer R2}`
      ? GreaterThan<R1, R2, S extends '=' ? GetSymbol<A, B> : S> : true
    : `${U}` extends `${any}${any}` ? false : S extends '>' ? true : false

感觉有点太丑陋了。

Solution by hesoso #29833

Solution 1:

My first idea was re-using the minusOne challenge solution which covers all test cases.

type Numbers = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type N_MinusOne = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8];

type ParseNumber<T extends string> = T extends `0${infer N extends number}` ? N : T extends `${infer R extends number}` ?  R : never;

type MinusOne<T extends number> = `${T}` extends `${infer R extends number}${Numbers}` ? 
                                      `${T}` extends `${R}${infer N extends number}` ? ParseNumber<(N extends 0 ? `${MinusOne<R>}${N_MinusOne[N]}` : `${R}${N_MinusOne[N]}`)> : N_MinusOne[T]:
                                    N_MinusOne[T];
// keep doing minus one until we reach U or hit 0
type GreaterThan<T extends number, U extends number, P extends number = MinusOne<T>> = T extends U ? false : P extends U ? true : P extends 0 ? false : GreaterThan<P, U>;


Solution 2:

After checking the solutions, i noticed most solution where using array, so i gave it a try

type ArrayLength<T extends number, Arr extends number[] = []> = Arr['length'] extends T ? Arr: ArrayLength<T, [...Arr, 1]>;

// fails on the last test case (1234567891011) Type instantiation is excessively deep and possibly infinite.
type GreaterThan<T extends number, U extends number, A extends number[] = ArrayLength<T>> = A[U] extends 1 ? true : false;

Solution by rezof #29758

// compares two strings by length. Returns:
// * `true` if `A` is longer
// * `false` if `B` is longer
// * `"equal"` if `A` and `B` are the same length
type LongerThen<A extends string, B extends string> =
  A extends `${string}${infer AR}`
    ? B extends `${string}${infer BR}`
      ? LongerThen<AR, BR>
      : true
    : B extends `${infer _}${string}`
      ? false
      : 'equal'

// Compare two numbers of the same length. Iterates digit-by-digit searching
// for the first non-equal. After found - compare. If non is found - return `false`
type GreaterThanForEqualLength<A extends string, B extends string>
  = [A, B] extends [`${infer AF}${infer AR}`, `${infer BF}${infer BR}`]
    ? AF extends BF
      ? GreaterThanForEqualLength<AR, BR>
      : '9876543210' extends `${string}${AF}${string}${BF}${string}`
        ? true
        : false
    : false


// Compare by length. If length is equal - compare by the first non-equal digit
type GreaterThan<A extends number, B extends number, ByLengthResult = LongerThen<`${A}`, `${B}`>> =
  ByLengthResult extends 'equal'
    ? GreaterThanForEqualLength<`${A}`, `${B}`>
    : ByLengthResult

Solution by Alexsey #29181

type Map = {
  "0": [];
  "1": ["0"];
  "2": ["1", "0"];
  "3": ["2", "1", "0"];
  "4": ["3", "2", "1", "0"];
  "5": ["4", "3", "2", "1", "0"];
  "6": ["5", "4", "3", "2", "1", "0"];
  "7": ["6", "5", "4", "3", "2", "1", "0"];
  "8": ["7", "6", "5", "4", "3", "2", "1", "0"];
  "9": ["8", "7", "6", "5", "4", "3", "2", "1", "0"];
};

type Includes<T, U> = T extends [infer F, ...infer R]
  ? Equal<F, U> extends true
    ? true
    : Includes<R, U>
  : false;

// 문자열로 변환해 길이로 비교할 수 있다.
type GreaterByStringLength<
  S1 extends string,
  S2 extends string
> = S1 extends `${string}${infer S1R}`
  ? S2 extends `${string}${infer S2R}`
    ? GreaterByStringLength<S1R, S2R>
    : true
  : false;

type GreaterByDigit<
  S1 extends string,
  S2 extends string
> = S1 extends `${infer S1F extends keyof Map}${infer S1R}`
  ? S2 extends `${infer S2F}${infer S2R}`
    ? S1F extends S2F // 두 자릿수가 같으면 재귀로 다음 자릿수로
      ? GreaterByDigit<S1R, S2R>
      : Includes<Map[S1F], S2F> extends true
      ? true
      : false
    : false
  : false;

// 1. 두 숫자가 동일한 경우 false
// 2. 문자열로 변환해 길이를 비교한다. A에 B를 비교.
// 3. 문자열로 변환해 길이를 비교한다. B에 A를 비교.
// 4. 두 숫자가 길이가 동일한 경우, 자릿수로 비교.
type GreaterThan<T extends number, U extends number> = T extends U
  ? false
  : GreaterByStringLength<`${T}`, `${U}`> extends true
  ? true
  : GreaterByStringLength<`${U}`, `${T}`> extends true
  ? false
  : GreaterByDigit<`${T}`, `${U}`>;

Solution by DoGukKim #28791

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

type GreaterThan<
  T extends number,
  U extends number,
  UArr extends number[] = GetArr<U>,
  ArrChecker extends number[] = []
> = T extends U
  ? false
  : UArr["length"] extends T
  ? true
  : ArrChecker["length"] extends T
  ? false
  : GreaterThan<T, U, [...UArr, 1], [...ArrChecker, 1]>;

Solution by idebbarh #28775

Get the number length

type StrLen<
  T extends string,
  Arr extends unknown[] = []
> = T extends `${string}${infer Rest}`
  ? StrLen<Rest, [...Arr, string]>
  : Arr["length"];

Check if numbers are equal

type isEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B
  ? 1
  : 2
  ? true
  : false;

If the numbers length are equal,we should compare every single bit

type ComapreChar<T, U> = T extends `${infer A extends number}${infer R1}`
  ? U extends `${infer B extends number}${infer R2}`
    ? isEqual<A, B> extends true
      ? ComapreChar<R1, R2>
      : InnerGreaterThan<A, B>
    : false
  : false;

Use "Fill Array" method for comparing small number

type InnerGreaterThan<
  T extends number,
  U extends number,
  Arr extends unknown[] = []
> = Arr["length"] extends T
  ? false
  : Arr["length"] extends U
  ? true
  : InnerGreaterThan<T, U, [...Arr, unknown]>;

First,compare the nums length if they are equal.If they are equal,compare every single bit(left to right).Otherwise,just compare the nums length.

type GreaterThan<
  T extends number,
  U extends number,
  TL extends number = StrLen<`${T}`>,
  UL extends number = StrLen<`${U}`>
> = isEqual<TL, UL> extends true
  ? ComapreChar<`${T}`, `${U}`>
  : InnerGreaterThan<TL, UL>;

Solution by DoubleWoodLin #28739

// K running to T and U , first got U true type GreaterThan< T extends number, U extends number, K extends any[] = [],

= K['length'] extends U | T ? K['length'] extends U ? K['length'] extends T ? false : true : false : GreaterThan<T, U, [...K, 1]>

// 你的答案

Solution by xpbsm #28463