00274-extreme-integers-comparator

Back

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>;

type LengthOfString<
  S extends string,
  T extends string[] = []
> = S extends `${infer F}${infer R}`
  ? LengthOfString<R, [...T, F]>
  : T["length"];

type PositiveGreaterThan<T extends string, U extends string> = GreaterThan<
  LengthOfString<T>,
  LengthOfString<U>
> extends true
  ? true
  : GreaterThan<LengthOfString<U>, LengthOfString<T>> extends true
  ? false
  : [T, U] extends [
      `${infer F1 extends number}${infer R1}`,
      `${infer F2 extends number}${infer R2}`
    ]
  ? F1 extends F2
    ? PositiveGreaterThan<R1, R2>
    : GreaterThan<F1, F2>
  : [T, U] extends [`${infer F1 extends number}`, `${infer F2 extends number}`]
  ? GreaterThan<F1, F2>
  : false;

type NegativeGreaterThan<
  T extends number,
  U extends number
> = `${T}` extends `-${infer T1}`
  ? `${U}` extends `-${infer U1}`
    ? PositiveGreaterThan<U1, T1>
    : false
  : `${U}` extends `-${string}`
  ? true
  : PositiveGreaterThan<`${T}`, `${U}`>;

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Comparator<A extends number, B extends number> = A extends B
  ? Comparison.Equal
  : NegativeGreaterThan<A, B> extends true
  ? Comparison.Greater
  : Comparison.Lower;

Solution by vangie #32346

enum Comparison {
	Greater,
	Equal,
	Lower,
}

type CharComp<A, B, I extends 1[] = [], L = `${I["length"]}`> = A extends B
	? Comparison.Equal
	: L extends A
		? Comparison.Lower
		: L extends B
			? Comparison.Greater
			: CharComp<A, B, [...I, 1]>;

type NaturalComp<
	A extends string,
	B extends string,
	C = Comparison.Equal,
> = A extends `${infer CA}${infer LA}`
	? B extends `${infer CB}${infer LB}`
		? NaturalComp<LA, LB, C extends Comparison.Equal ? CharComp<CA, CB> : C>
		: Comparison.Greater
	: B extends `${number}`
		? Comparison.Lower
		: C;

type Comparator<A extends number | bigint, B extends number | bigint> = `${A}` extends `-${infer X}`
	? `${B}` extends `-${infer Y}`
		? NaturalComp<Y, X>
		: Comparison.Lower
	: `${B}` extends `-${infer Y}`
		? Comparison.Greater
		: NaturalComp<`${A}`, `${B}`>;

Solution by alexandroppolus #32282

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

type MarkArr<N extends number, R extends unknown[] = []> = R['length'] extends N ? R : MarkArr<N, [0, ...R]>;
type Plus<A extends number, B extends number> = [...MarkArr<A>, ...MarkArr<B>]['length'];

type String2Number<S extends string, T extends any[] = []> = `${S}` extends `${T['length']}`
  ? T['length']
  : String2Number<S, [0, ...T]>;
  // 对比两个数字大小
type CompareNumber<A extends number, B extends number> = keyof MarkArr<A> extends keyof MarkArr<B>
  ? Comparison.Lower
  : Comparison.Greater;

// 生成对照表
type NumberMap = {
  [Key in `${num[number]}${num[number]}`]: Key extends `${infer A}${infer B}`
    ? CompareNumber<String2Number<A>, String2Number<B>>
    : never;
};

// 对比长度
  type ComparisonNumberArr<
  S extends string[],
  E extends string[],
  P extends number = 0,
> =
// 长度是否相同
  S['length'] extends E['length']
  // 长度相同,则开始从P(默认是第一位0)位开始计算
  ? S[P] extends E[P]
  // 如果相同,则P指针加1,继续计算
    ? ComparisonNumberArr<S, E, Plus<P, 1> & number>
    // 类型收窄
    : `${S[P]}${E[P]}` extends keyof NumberMap
      ? NumberMap[`${S[P]}${E[P]}`]
      : never
      // 长度不相同,则对比长度就可以知道大小了
  : CompareNumber<S['length'], E['length']>;

// 数字转为字符串的数组
type TowNumberArray<
  T extends string | number,
  A extends string[] = [],
> = `${T}` extends `${infer S}${infer O}` ? TowNumberArray<O, [...A, S]> : A;

type Comparator<M extends number, N extends number> =
// 相等
 M extends N
  ? Comparison.Equal
  // 都是负数,则反转计算的结果
  : `${M}${N}` extends `-${infer M1}-${infer N1}`
    ? ComparisonNumberArr<TowNumberArray<M1>, TowNumberArray<N1>> extends Comparison.Lower
      ? Comparison.Greater
      : Comparison.Lower
      // 第一个为负数
    : `${M}${N}` extends `-${infer M1}${infer N1}`
      ? Comparison.Lower
      // 第二个为负数
      : `${M}${N}` extends `${infer M1}-${infer N1}`
        ? Comparison.Greater
        //  都是正数
        : `${M}${N}` extends `${infer M2}${infer N2}`
          ? ComparisonNumberArr<TowNumberArray<M>, TowNumberArray<N>>
          : never;

Solution by jiangxd2016 #31573

// your answers

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

type IsFNumber<T extends string | number> = `${T}` extends `-${number}` ? true : false

type GetNumber<T extends string | number> = `${T}` extends `-${infer N}` ? N : T

type NTCompare<T extends string | number, N extends string | number> = IsFNumber<T> extends IsFNumber<N> ? never : IsFNumber<T> extends true ? Comparison.Lower : Comparison.Greater

type GetNumberArray<T extends string | number, R extends number[] = []> = `${R['length']}` extends `${T}` ? R : GetNumberArray<T, [...R, 0]>

type EasyCompare<A extends string | number, B extends string | number> = 
GetNumberArray<GetNumber<A>> extends [...GetNumberArray<GetNumber<B>>, ...number[]] 
? IsFNumber<A> extends true ? Comparison.Lower : Comparison.Greater 
: IsFNumber<A> extends true ? Comparison.Greater : Comparison.Lower;

type EComparator<A extends string | number, B extends string | number> = NTCompare<A, B> extends never ? MyEqual<A, B> extends true ? Comparison.Equal : EasyCompare<A, B> : NTCompare<A, B>

type Comparator<A extends string | number, B extends string | number> = NTCompare<A, B> extends never ? MyEqual<A, B> extends true ? Comparison.Equal : 
IsFNumber<A> extends true ? PEasyCompare<GetNumberPArray<B>, GetNumberPArray<A>> : PEasyCompare<GetNumberPArray<A>, GetNumberPArray<B>> : NTCompare<A, B>

type GetNumberPArray<T extends number | string> = `${T}` extends `${infer F}${infer Rest}` ? [F, ...GetNumberPArray<Rest>] : []

type PEasyCompare<A extends Array<string | number>, B extends Array<string | number>> = EComparator<A['length'], B['length']> extends Comparison.Equal 
? PCompare<A, B> 
: EComparator<A['length'], B['length']>

type GetFirst<T extends any[]> = T[0];

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

type PCompare<A extends any[], B extends any[]> = EComparator<GetFirst<A>, GetFirst<B>> extends Comparison.Equal ? 
A['length'] extends 1 ? Comparison.Equal : PCompare<GetRest<A>, GetRest<B>> : EComparator<GetFirst<A>, GetFirst<B>>

Solution by 437204933 #29922

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}`>;

Solution by Royce-DaDaDa #29831

type IsNegative<N extends number | `${number}`> = `${N}` extends `-${number}` ? true : false;

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


enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Comparator<A extends number | `${number}`, B extends number | `${number}`> = A extends B
  ? Comparison.Equal
  : [IsNegative<A>, IsNegative<B>] extends [true, false]
  ? Comparison.Lower
  : [IsNegative<A>, IsNegative<B>] extends [false, true]
  ? Comparison.Greater
  : [IsNegative<A>, IsNegative<B>] extends [true, true]
  ? [`${A}`, `${B}`] extends [`-${infer APositive}`, `-${infer BPositive}`]
    ? Comparator.ComparePositiveNumbers<Comparator.SplitNumber<BPositive>, Comparator.SplitNumber<APositive>>
    : never
  : Comparator.ComparePositiveNumbers<Comparator.SplitNumber<A>, Comparator.SplitNumber<B>>;

namespace Comparator {
  export type ComparePositiveNumbers<
    A extends number[],
    B extends number[],
  > = `${A['length']}` extends keyof B & `${number}`
    ? Comparison.Lower
    : `${B['length']}` extends keyof A & `${number}`
    ? Comparison.Greater
    : CompareEqualLengthNumbers<A, B>;

  type CompareEqualLengthNumbers<A extends number[], B extends number[]> = [A, B] extends [
    [infer A0 extends number, ...infer ARest extends number[]],
    [infer B0 extends number, ...infer BRest extends number[]],
  ]
    ? CompareNumbers<A0, B0> extends Comparison.Equal
      ? CompareEqualLengthNumbers<ARest, BRest>
      : CompareNumbers<A0, B0>
    : Comparison.Equal;

  type CompareNumbers<A extends number, B extends number> = A extends B
    ? Comparison.Equal
    : `${A}` extends keyof NumberToTuple<B> & `${number}`
    ? Comparison.Lower
    : Comparison.Greater;

  export type SplitNumber<N extends number | string> =
    `${N}` extends `${infer N0 extends number}${infer NRest extends string}`
      ? [N0, ...SplitNumber<NRest>]
      : [];
}

Playground

Solution by BOCbMOU #27800

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type GreatConfig  = {
  "0": '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'| '9'
  "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 CompareDigit<
  A extends string,
  B extends string,
> = 
  A extends B?
    Comparison.Equal:
    A extends keyof GreatConfig?
      B extends GreatConfig[A]?
        Comparison.Lower:Comparison.Greater
      :never

type CompareDigits<
  A extends string,
  B extends string,
> = 
  [A,B] extends [`${infer AF}${infer AR}`,`${infer BF}${infer BR}`]?
    CompareDigit<AF,BF> extends infer CR?
      CR extends Comparison.Equal?
        CompareDigits<AR,BR>
        :CR
    :never
  : Comparison.Equal


type CompareByLength<
  A extends string,
  B extends string,
> = 
  A extends `${infer AF}${infer AR}`?
    B extends `${infer BF}${infer BR}`?
      CompareByLength<AR,BR>:
      Comparison.Greater
    : B extends `${infer BF}${infer BR}`?
      Comparison.Lower:Comparison.Equal


type CompareNonNegative<
  A extends string,
  B extends string,
  ByLength extends Comparison = CompareByLength<A,B>
> = 
  ByLength extends Comparison.Equal?
    CompareDigits<A,B>:
    ByLength


type Comparator<
  A extends number, 
  B extends number
> = 
`${A}` extends `-${infer ABS_A}`?
  `${B}` extends `-${infer ABS_B}`?
    CompareNonNegative<ABS_B,ABS_A>
    : Comparison.Lower
  : `${B}` extends `-${infer ABS_B}`?
    Comparison.Greater
    : CompareNonNegative<`${A}`,`${B}`>

Solution by jiangshanmeta #27759

// Improved version
type CompareDigits<D1 extends string, D2 extends string> = D1 extends D2
  ? Comparison.Equal
  : '9876543210' extends `${string}${D1}${string}${D2}${string}`
  ? Comparison.Greater
  : Comparison.Lower;

type ComparePositiveIntegers<
  A extends string,
  B extends string,
  TempResult extends Comparison = Comparison.Equal
> = A extends `${infer AF}${infer AR}`
  ? B extends `${infer BF}${infer BR}`
    ? TempResult extends Comparison.Equal
      ? ComparePositiveIntegers<AR, BR, CompareDigits<AF, BF>>
      : ComparePositiveIntegers<AR, BR, TempResult>
    : Comparison.Greater
  : B extends `${infer _}${infer __}`
  ? Comparison.Lower
  : TempResult;

type Comparator<
  A extends number,
  B extends number
> = `${A}` extends `-${infer AbsA}`
  ? `${B}` extends `-${infer AbsB}`
    ? ComparePositiveIntegers<AbsB, AbsA>
    : Comparison.Lower
  : `${B}` extends `-${number}`
  ? Comparison.Greater
  : ComparePositiveIntegers<`${A}`, `${B}`>;

Reference 1 Reference 2

// My own version
type NumberToTuple<T, U extends 1[] = []> = U['length'] extends T
  ? U
  : NumberToTuple<T, [...U, 1]>;

type GreaterOrEqual<
  A extends number,
  B extends number
> = NumberToTuple<A> extends [...NumberToTuple<B>, ...infer _] ? true : false;

type StringLength<
  S extends string,
  T extends 1[] = []
> = S extends `${infer _}${infer R}` ? StringLength<R, [...T, 1]> : T['length'];

type EqualLengthStringComparator<
  A extends string,
  B extends string
> = A extends `${infer A1 extends number}${infer AR}`
  ? B extends `${infer B1 extends number}${infer BR}`
    ? A1 extends B1
      ? EqualLengthStringComparator<AR, BR>
      : GreaterOrEqual<A1, B1> extends true
      ? Comparison.Greater
      : Comparison.Lower
    : Comparison.Equal
  : Comparison.Equal;

type PositivesComparator<
  A extends number,
  B extends number,
  ALen extends number = StringLength<`${A}`>,
  BLen extends number = StringLength<`${B}`>
> = ALen extends BLen
  ? EqualLengthStringComparator<`${A}`, `${B}`>
  : GreaterOrEqual<ALen, BLen> extends true
  ? Comparison.Greater
  : Comparison.Lower;

type Comparator<A extends number, B extends number> = A extends B
  ? Comparison.Equal
  : `${A}` extends `-${infer T extends number}`
  ? `${B}` extends `-${infer U extends number}`
    ? PositivesComparator<U, T>
    : Comparison.Lower
  : `${B}` extends `-${number}`
  ? Comparison.Greater
  : PositivesComparator<A, B>;

Solution by JohnLi1999 #26784

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> = `${T}` extends `${infer F}${any}` ? F : ``;
/**更低位 */
type DigitLowerRest<T extends number | 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)
      ))
  );

enum Comparison {
  Greater,
  Equal,
  Lower,
}
type Comparator<A extends number | string, B extends number | 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>);

Solution by E-uler #25523

enum Comparison {
  Greater,
  Equal,
  Lower,
}
// -7 -> '7'
type AbsVal<T extends number> = `${T}` extends `-${infer A}` ? A : `${T}`
type IsNegative<T extends number> = `${T}` extends `-${infer A}` ? true : false
type NotAllZero<A extends number, B extends number> = AbsVal<A> extends '0'? AbsVal<B> extends '0'? false: true: true

type GreaterThan<A extends number,B extends number,C extends boolean,R1,R2,N extends number[] = []> = 
  IsNegative<B> extendsC
  ? R1
  : `${AbsVal<A>}` extends `${N['length']}`
  ? R2
  : `${AbsVal<B>}` extends `${N['length']}`
  ? R1
  : GreaterThan<A, B, C, R1, R2, [...N, 0]>

type Comparator<A extends number, B extends number, N extends number[] = []> = 
  NotAllZero<A,B> extends false
  ? Comparison.Equal
  : A extends B
  ? Comparison.Equal
  : IsNegative<A> extends true
  ? GreaterThan<A, B, false, Comparison.Lower, Comparison.Greater, N>
  : GreaterThan<A, B, true, Comparison.Greater, Comparison.Lower, N>

Solution by TKBnice #23777

// your answers
enum Comparison {
  Greater,
  Equal,
  Lower,
}
// 判断是否是负数
type IsNegative<T extends number> = `${T}` extends `-${number}` ? true : false;
type NegativeToPositive<T extends number> =
  `${T}` extends `-${infer R extends number}` ? R : never;
// 比较 0~9 这样的两个数大小, 判断 A > B 是否成立
type GreaterThan<
  A extends number,
  B extends number,
  I extends 0[] = []
> = A extends B
  ? false
  : I["length"] extends A
  ? I["length"] extends B
    ? false
    : false
  : I["length"] extends B
  ? true
  : GreaterThan<A, B, [0, ...I]>;
// 获取最大值
type GetMax<A extends number, B extends number> = GreaterThan<
  A,
  B
> extends true
  ? A
  : B;

// 获取字符串长度
type GetStringLength<
  S extends string,
  I extends 0[] = []
> = S extends `${string}${infer R}`
  ? GetStringLength<R, [0, ...I]>
  : I["length"];

// 将字符串用0补全到指定位数
type FillZero<
  S extends string,
  N extends number
> = GetStringLength<S> extends N ? S : FillZero<`0${S}`, N>;

// 1. 两个都是正数的情况
// 2. 两个都是负数的情况
// 3. 一正一负的情况

// 传入的字符串会补到一样的长度 00000
type PositiveComparator<
  A extends string,
  B extends string,
  isNeg extends boolean = false
> = A extends B
  ? Comparison.Equal
  : A extends `${infer AF extends number}${infer AR}`
  ? B extends `${infer BF extends number}${infer BR}`
    ? AF extends BF
      ? PositiveComparator<AR, BR, isNeg>
      : GreaterThan<AF, BF> extends true
      ? isNeg extends true
        ? Comparison.Lower
        : Comparison.Greater
      : isNeg extends true
      ? Comparison.Greater
      : Comparison.Lower
    : never
  : never;
// 处理一正一负的情况
type NegAndPosComparator<
  A extends number,
  B extends number
> = `${A}` extends `-${number}` ? Comparison.Lower : Comparison.Greater;
type Comparator<
  A extends number,
  B extends number,
  MaxLen extends number = GetMax<
    GetStringLength<`${A}`>,
    GetStringLength<`${B}`>
  >
> = [IsNegative<A> | IsNegative<B>] extends [true]
  ? PositiveComparator<
      FillZero<`${NegativeToPositive<A>}`, MaxLen>,
      FillZero<`${NegativeToPositive<B>}`, MaxLen>,
      true
    >
  : [IsNegative<A> | IsNegative<B>] extends [false]
  ? PositiveComparator<FillZero<`${A}`, MaxLen>, FillZero<`${B}`, MaxLen>>
  : NegAndPosComparator<A, B>

Solution by acwink #22178

enum Comparison {
  Greater,
  Equal,
  Lower,
}

// compare one bit chars of number without mark
type CompareOne<A extends string, B extends string> =
  A extends B
  ? Comparison.Equal
  : '0123456789' extends `${any}${A}${any}${B}${any}`
    ? Comparison.Lower
    : Comparison.Greater

// reverse a string
type Reverse<S extends string> = S extends `${infer F}${infer Rest}` ? `${Reverse<Rest>}${F}` : ''

// compare positive numbers in string format
type ComparePositiveNumbers<A extends string, B extends string> = 
  Reverse<A> extends `${infer ALast}${infer ARest}`
  ? Reverse<B> extends `${infer BLast}${infer BRest}`
    ? ComparePositiveNumbers<Reverse<ARest>, Reverse<BRest>> extends Comparison.Equal
      ? CompareOne<ALast, BLast>
      : ComparePositiveNumbers<Reverse<ARest>, Reverse<BRest>>
    : Comparison.Greater
  : B extends ''
    ? Comparison.Equal
    : Comparison.Lower

// parse a number into [mark, value], where mark is + or -, and value is a string of number without mark
type ParseNumber<N extends number | string> =
 `${N}` extends `-${infer V extends number}`
 ? ['-', `${V}`]
 : ['+', `${N}`]

type Comparator<A extends number | string, B extends number | string> = 
  ParseNumber<A> extends [infer AM, infer AV extends string]
  ? ParseNumber<B> extends [infer BM, infer BV extends string]
    ? AM extends '-'
      ? BM extends '-'
        ? ComparePositiveNumbers<BV, AV> // - -
        : Comparison.Lower // - +
      : BM extends '-'
        ? Comparison.Greater // + -
        : ComparePositiveNumbers<AV, BV> // + +
    : never
  : never

playground

Solution by zhaoyao91 #22128

```ts
enum Comparison {
  Greater,
  Equal,
  Lower,
}

type BigPositiveGreaterThan<
  A extends string,
  B extends string,
  LA = LengthOfString<A>,
  LB = LengthOfString<B>,
> = LA extends LB
  ? A extends `${infer AF extends number}${infer AR}`
    ? B extends `${infer BF extends number}${infer BR}`
      ? AF extends BF
        ? BigPositiveGreaterThan<AR, BR>
        : GreaterThan<AF, BF>
      : false
    : never
  : GreaterThan<LengthOfString<A>, LengthOfString<B>>

  type PositiveComparator<
    X extends number,
    Y extends number,
  > = BigPositiveGreaterThan<`${X}`, `${Y}`> extends true
    ? Comparison.Greater
    : Comparison.Lower

type Comparator<A extends number, B extends number> = A extends B
  ? Comparison.Equal
  : `${A}` extends `-${infer X extends number}`
    ? `${B}` extends `-${infer Y extends number}`
      ? PositiveComparator<Y, X>
      : Comparison.Lower
    : `${B}` extends `-${number}`
      ? Comparison.Greater
      : PositiveComparator<A, B>

Solution by thanhhtse04588 #22013

Playground.

enum Comparison {
  Greater,
  Equal,
  Lower,
}

// # 4425
type _GreaterThanForPos<T extends number, U extends number, _Counter extends 0[] = []> =
  _Counter['length'] extends T
    ? _Counter['length'] extends U
      ? Comparison.Equal
      : Comparison.Lower
    : _Counter['length'] extends U
      ? Comparison.Greater
      : _GreaterThanForPos<T, U, [ ..._Counter, 0 ]>

// Limit version
// type Comparator<
//   A extends number,
//   B extends number,
// > = `${ A },${ B }` extends `-${ infer IA extends number },-${ infer IB extends number }`
//   ? _GreaterThanForPos<IB, IA>
//   : `${ A },${ B }` extends `${ number },-${ number }`
//     ? Comparison.Greater
//     : `${ A },${ B }` extends `-${ number },${ number }`
//       ? Comparison.Lower
//       : _GreaterThanForPos<A, B>


type _RemoveZeroes<T extends string> =
  `${ T }` extends `${ infer A extends string }0${ infer B extends string }`
    ? B extends '' | '0' ? T : _RemoveZeroes<`${ A }${ B }`>
    : T

type _CountStringLength<T extends string, _Counter extends 0[] = []> =
  T extends `${ string }${ infer Rest }`
    ? _CountStringLength<Rest, [ ..._Counter, 0 ]>
    : _Counter['length']

type _ComparatorNumberLengthForPos<
  A extends number,
  B extends number,
  _A extends string = `${ A }` extends `${ infer I extends string }` ? I : never,
  _B extends string = `${ B }` extends `${ infer I extends string }` ? I : never,
> = _GreaterThanForPos<_CountStringLength<_A>, _CountStringLength<_B>>

type _ComparatorEqualLengthForPos<
  A extends number,
  B extends number,
  _A extends string = `${ A }` extends `${ infer I extends string }` ? _RemoveZeroes<I> : never,
  _B extends string = `${ B }` extends `${ infer I extends string }` ? _RemoveZeroes<I> : never,
> = _A extends `${ infer FA extends number }${ infer RestA extends number }`
  ? _B extends `${ infer FB extends number }${ infer RestB extends number }`
    ? FA extends FB
      ? _ComparatorEqualLengthForPos<RestA, RestB>
      : _GreaterThanForPos<FA, FB>
    : never
  : _GreaterThanForPos<A, B>

// No limit
type Comparator<A extends number, B extends number> =
  `${ A },${ B }` extends `-${ infer IA extends number },-${ infer IB extends number }`
    ? _ComparatorNumberLengthForPos<IA, IB> extends Comparison.Equal
      ? _ComparatorEqualLengthForPos<IB, IA>
      : _ComparatorNumberLengthForPos<IB, IA>
    : `${ A },${ B }` extends `${ number },-${ number }`
      ? Comparison.Greater
      : `${ A },${ B }` extends `-${ number },${ number }`
        ? Comparison.Lower
        : _ComparatorNumberLengthForPos<A, B> extends Comparison.Equal
          ? _ComparatorEqualLengthForPos<A, B>
          : _ComparatorNumberLengthForPos<A, B>

Solution by lvjiaxuan #21929

Solution

type IntADT = number | string | bigint;
type DigitLUT = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
type Digit = DigitLUT[number];

type Comparator<
  A extends IntADT, 
  B extends IntADT, 
  IS_SIGN_SYMMETRIC extends boolean = SignSymmetry<A, B> extends -1 ? false : true,
  RESULT extends Comparison = Equal<A, B> extends true ? Comparison.Equal
    : IS_SIGN_SYMMETRIC extends true
      ? IsNonNegative<A> extends true
        ? UnsignedIntComparator<A, B> : UnsignedIntComparator<Absolute<B>, Absolute<A>>
      : IsNonNegative<A> extends true
        ? Comparison.Greater : Comparison.Lower
> = RESULT;

type UnsignedIntComparator<
  A extends IntADT, 
  B extends IntADT,
  A_LENGTH extends number = IntLength<A>, 
  B_LENGTH extends number = IntLength<B>, 
  A_MSD extends Digit = MSD<A>,
  B_MSD extends Digit = MSD<B>,
  A_NEXT extends string | '' = DropMSD<A>,
  B_NEXT extends string | '' = DropMSD<B>,
  COMP extends Comparison = DigitComparator<A_MSD, B_MSD>,
  RESULT extends Comparison = Equal<A_LENGTH, B_LENGTH> extends false 
    ? UnsignedIntComparator<A_LENGTH, B_LENGTH>
    : All<[IsDigit<A>, IsDigit<B>]> extends true
      ? COMP
      : COMP extends Comparison.Equal
        ? UnsignedIntComparator<A_NEXT, B_NEXT>
        : COMP
> = RESULT;

type DigitComparator<
  A extends IntADT, 
  B extends IntADT, 
  PREV extends Digit[] = DigitLUT,
  CURR extends IntADT = PREV[0],
  IS_A extends boolean = Equal<`${A}`, `${CURR}`>,
  IS_B extends boolean = Equal<`${B}`, `${CURR}`>,
  NEXT extends Digit[] = Shift<PREV>,
  RESULT extends Comparison = IS_A extends true
    ? IS_B extends true ? Comparison.Equal : Comparison.Lower
    : IS_B extends true ? Comparison.Greater : DigitComparator<A, B, NEXT>
> = RESULT;
/** Helpers */
type IsDigit<N extends IntADT> = 
  `${N}` extends Digit ? true : false;

type IntLength<N extends IntADT, M extends Digit[] = []> = 
  `${N}` extends `${infer D extends Digit}${infer Rest}` ? IntLength<Rest, Push<M, D>> : M["length"];

/** @returns Digit */
type MSD<N extends IntADT> = 
  `${N}` extends `${infer H extends Digit}${string}` ? H : '0';

/** @returns string | '' */
type DropMSD<N extends IntADT> = 
  `${N}` extends `${infer H extends Digit}${infer Rest}` ? Rest : never;

type Signum<N extends IntADT> = 
  `${N}` extends '0' ? 0
    : `${N}` extends `-${infer _}` ? -1 : 1;

type SignSymmetry<A extends IntADT, B extends IntADT> = 
  `${A}` extends `${B}` ? 0
    : Any<[All<[IsNonNegative<A>, IsNonNegative<B>]>, All<[IsNegative<A>, IsNegative<B>]>]> extends true 
      ? 1 : -1;
    
type IsNonNegative<N extends IntADT> = 
  IsNegative<N> extends false ? true : false;

type IsNegative<N extends IntADT> = 
  Signum<N> extends -1 ? true : false;

type Absolute<N extends IntADT> = 
  IsNegative<N> extends true
    ? `${N}` extends `-${infer R extends number}` ? R : N
    : N;

/** Utilities */
type All<T extends boolean[]> = 
  T extends [infer B, ...infer Rest extends boolean[]]
    ? B extends true ? All<Rest> : false
    : true;

type Shift<T extends any[], N extends number = 1> = 
  N extends 0 ? T 
    : T extends [infer _, ...infer Rest]
      ? Shift<Rest, Subtract<N, 1>>
      : [];

JS translation

(For reference, in case any part of the above is unclear.)

function Comparator(A, B) {
  if (SignSymmetry(A, B) === 0) return Comparison.Equal
  if (SignSymmetry(A, B) === 1) {
    if (A >= 0) return UnsignedIntComparator(A, B)
    else return InvertComparison(UnsignedIntComparator(Absolute(A), Absolute(B)))
  }
  if (SignSymmetry(A, B) === -1) {
    if (A >= 0) return Comparison.Greater
    else return Comparison.Lower
  }
}

function UnsignedIntComparator(A, B) {
  if (IntLength(A) === IntLength(B)) {
    if (IntLength(A) === 1 && IntLength(B) === 1) return SingleDigitComparator(A, B)
    for (const MSD_A of String(A)) {
      for (const MSD_B of String(B)) {
        if (MSD_A === MSD_B) return UnsignedIntComparator(String(A).slice(1), String(B).slice(1))
        return SingleDigitComparator(MSD_A, MSD_B)
      }
    } 
  } else return UnsignedIntComparator(IntLength(A), IntLength(B))
}

function SingleDigitComparator(A, B, M = [0,1,2,3,4,5,6,7,8,9]) {
  if (A === M[0]) {
    if (B === M[0]) return Comparison.Equal
    else return Comparison.Lower
  } else {
    if (B === M[0]) return Comparison.Greater
    else return SingleDigitComparator(A, B, M.slice(1))
  }
}

function SignSymmetry(A, B) {
  if (A === B) return 0
  if (A >= 0 && B >= 0 || A < 0 && B < 0) return +1
  else return -1
}

Discussion

type len1 = IntLength<0>
type len16 = IntLength<1234567891234567>
type len16_maxsafe = IntLength<9007199254740992>
type len21 = IntLength<123456789123456789123>
type len22* = IntLength<1234567891234567891234>
type len23_str = IntLength<'12345678912345678912345'>
type len26_str = IntLength<'abcdefghijklmnopqrstuvwxyz'>

const len16_maxsafe = `${9007199254740992}` as const // 9007199254740992
const len17 = `${12345678912345678}` as const // 12345678912345678
const len18_rounded = `${123456789123456789}` as const // 123456789123456780
const len21_rounded = `${123456789123456789123}` as const // 123456789123456800000
const len22_scientific = `${1234567891234567891234}` as const // "1.234567891234568e+21"
const len22-1 = `${1234567891234567891234}`.length // 21
type Comparator<A extends number | string, B extends number | string> = 

Room for improvement

Solution by MajorLift #21601

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Build<
  T extends number,
  Result extends Array<never> = []
> = Result["length"] extends T ? Result : Build<T, [...Result, never]>;

type EGT<T extends number, B extends number> = Build<T> extends [
  ...Build<B>,
  ...infer C
]
  ? true
  : false;

type InferNum<T extends number> = `${T}` extends `-${infer A extends number}`
  ? A
  : T;

type Comparator_<A extends number, B extends number> = EGT<
  InferNum<A>,
  InferNum<B>
> extends true
  ? Comparison.Greater
  : Comparison.Lower;


  type Comparator<A extends number, B extends number> = A extends B
  ? Comparison.Equal
  : [
      `${A}` extends `-${infer A1 extends number}` ? true : false,
      `${B}` extends `-${infer B1 extends number}` ? true : false
    ] extends [true, true]
  ? Comparator_<B, A>
  : [
      `${A}` extends `-${infer A1 extends number}` ? true : false,
      `${B}` extends `${infer B1 extends number}` ? true : false
    ] extends [true, true]
  ? Comparison.Lower
  : [
      `${A}` extends `${infer A1 extends number}` ? true : false,
      `${B}` extends `-${infer B1 extends number}` ? true : false
    ] extends [true, true]
  ? Comparison.Greater
  : Comparator_<A,B>;

Solution by so11y #21394

type ComparatorPos<N1 extends number, N2 extends number, arr extends number[] = []> = 
    arr['length'] extends N1 ? (arr['length'] extends N2 ? Comparison.Equal : Comparison.Lower)
    : arr['length'] extends N2 ? Comparison.Greater
    : ComparatorPos<N1, N2, [...arr, arr['length']]>;

type Comparator<A extends number, B extends number> = 
  `${A}` extends `-${infer APos extends number}`
  ? `${B}` extends `-${infer BPos extends number}`
    ? ComparatorPos<BPos, APos>
    : Comparison.Lower
  : `${B}` extends `-${infer BPos extends number}`
    ? Comparison.Greater
    : ComparatorPos<A, B>;

Solution by mdakram28 #20677

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type TenTimesArray<T extends unknown[]> = [
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T,
  ...T
]

type ArrayWithinTen<
  T extends string | number,
  R extends unknown[] = []
> = `${R['length']}` extends `${T}` ? R : ArrayWithinTen<T, [unknown, ...R]>

type ArrayWithLength<
  T extends string | number,
  R extends unknown[] = []
> = `${T}` extends `${infer A}${infer B}`
  ? ArrayWithLength<B, [...TenTimesArray<R>, ...ArrayWithinTen<A>]>
  : R

type Pop<T extends unknown[]> = T extends [...infer A, unknown] ? A : T

type CompareNumber<
  T extends string | number,
  U extends string | number,
  N extends boolean = false,
  TA extends unknown[] = ArrayWithLength<T>,
  UA extends unknown[] = ArrayWithLength<U>
> = TA['length'] extends 0
  ? UA['length'] extends 0
    ? Comparison.Equal
    : N extends true
    ? Comparison.Greater
    : Comparison.Lower
  : UA['length'] extends 0
  ? N extends true
    ? Comparison.Lower
    : Comparison.Greater
  : CompareNumber<T, U, N, Pop<TA>, Pop<UA>>

type Comparator<
  A extends number,
  B extends number
> = `${A}` extends `-${infer C}`
  ? `${B}` extends `-${infer D}`
    ? CompareNumber<C, D, true>
    : Comparison.Lower
  : `${B}` extends `-${number}`
  ? Comparison.Greater
  : CompareNumber<A, B>

Solution by theoolee #19847

enum Comparison {
  Greater,
  Equal,
  Lower,
}
type Negative<A extends number> = `${A}` extends `-${infer N extends number}` ? N : false;
type Compare<A extends number, B extends number, C extends any[] = []> =
  C['length'] extends A
    ? Comparison.Lower
    : C['length'] extends B
      ? Comparison.Greater
      : Compare<A, B, [...C, any]>;
type Comparator<A extends number, B extends number> =
  A extends B
    ? Comparison.Equal
    : [Negative<A>, Negative<B>] extends [infer AA, infer BB]
      ? [AA, BB] extends [false, false]
        ? Compare<A, B>
        : [AA, BB] extends [false, number]
          ? Comparison.Greater
          : [AA, BB] extends [number, false]
            ? Comparison.Lower
            : Compare<BB & number, AA & number>
      : never;

Solution by BulatDashiev #16983

enum Comparison {
  Greater,
  Equal,
  Lower,
}

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

type IsMinus<A> = `${A & number}` extends `-${number}` ? true : false

type BuildArray<Len, Arr extends unknown[] = []> = Arr['length'] extends Len ? Arr : BuildArray<Len, [...Arr, unknown]>

type Compare<A extends number, B extends number> = BuildArray<A> extends [...BuildArray<B>, ...infer _] ? Comparison.Greater : Comparison.Lower

type Abs<T> = `${T & number}` extends `-${infer N extends number}` ? N : never

type Comparator<A extends number, B extends number> = IsEqual<A, B> extends true
  ? Comparison.Equal
  : IsMinus<A> extends true
    ? IsMinus<B> extends false
      ? Comparison.Lower
      : Compare<Abs<B>, Abs<A>>
    : IsMinus<B> extends true
      ? Comparison.Greater
      : Compare<A, B>

Solution by XkSuperCool #16936

type CheckInteger = T extends 0 ? 0 : ${T} extends -${infer R} ? -1 : 1;

type StringToNumber<T extends string, R extends 0[] = []> = ${R['length']} extends T ? R['length'] : StringToNumber<T, [...R, 0]>;

type ABS = ${T} extends -${infer R} ? StringToNumber : T;

type PositiveIntegerComparator<A extends number, B extends number, R extends 0[] = []> = A extends R['length'] ? B extends R['length'] ? Comparison.Equal : Comparison.Lower : B extends R['length'] ? Comparison.Greater : PositiveIntegerComparator<A, B, [...R, 0]>;

type Comparator<A extends number, B extends number> = CheckInteger extends 1 ? CheckInteger extends 1 ? PositiveIntegerComparator<A, B> : Comparison.Greater : CheckInteger extends -1 ? CheckInteger extends -1 ? PositiveIntegerComparator<ABS, ABS> : Comparison.Lower : CheckInteger extends 0 ? CheckInteger extends 0 ? Comparison.Equal : CheckInteger extends 1 ? Comparison.Lower : Comparison.Greater : never;

Solution by my5201314zwl #16804

// your answers

enum Comparison {
  Greater,
  Equal,
  Lower,
}

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 GT<T extends number, D extends number, E extends boolean = T extends D ? true : false> = E extends true ? false : T extends D
  ? true
  : T extends 0
    ? false
    : GT<MinusOne<T>, D, false>

type IsNegative<T extends number> = `${T}` extends `-${infer R extends number}`
  ? true
  : false

type ABS<T extends number> = `${T}` extends `-${infer R extends number}`
  ? R
  : T

type Comparator<A extends number, B extends number> = A extends B
  ? Comparison.Equal
  : IsNegative<A> extends true
    ? IsNegative<B> extends true
      ? Comparator<ABS<B>, ABS<A>>
      : Comparison.Lower
    : IsNegative<B> extends true
      ? Comparison.Greater
      : GT<A, B> extends true
        ? Comparison.Greater
        : Comparison.Lower

Solution by humandetail #16616

// your answers
enum Comparison {
  Greater,
  Equal,
  Lower,
} ;

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 Multyply<
    A extends readonly any[],
    B extends readonly any[]> =
    A extends [infer R,...infer U]
    ? [...B,...Multyply<U,B>]
    : []  ;

type ReverseString<
    S extends string> =
    S extends `${infer R extends string}${infer U extends string}`
    ? `${ReverseString<U>}${R}`
    : ''  ;

type ReverseStringToTuple<
    S extends string,
    E extends any = any> =
    S extends `${infer R extends keyof Dictionary<E>}${infer U extends string}`
    ? [...Dictionary<E>[R],...Multyply<_10<E>,ReverseStringToTuple<U>>]
    : []  ;

type Dif<
    A extends number,
    B extends number> =
    `${A}` extends `-${infer R extends number}`
    ? `${B}` extends `-${infer U extends number}`
    ? ReverseStringToTuple<ReverseString<`${A}`>> extends 
    [...ReverseStringToTuple<ReverseString<`${B}`>>,...infer R extends readonly any[]]
    ? `-${R['length'] }` extends `${infer N extends number}`
    ? N
    : never
    : ReverseStringToTuple<ReverseString<`${B}`>> extends 
    [...ReverseStringToTuple<ReverseString<`${A}`>>,...infer R extends readonly any[]]  
    ? R['length']
    : never
    : [...ReverseStringToTuple<ReverseString<`${A}`>>,...ReverseStringToTuple<ReverseString<`${B}`>>] extends
     infer R extends readonly any[]
    ? `-${R['length']}` extends `${infer N extends number}`
    ? N
    : never
    : never
    : `${B}` extends `-${infer U extends number}`
    ? [...ReverseStringToTuple<ReverseString<`${A}`>>,...ReverseStringToTuple<ReverseString<`${B}`>>] extends
     infer R extends readonly any[]
    ? R['length']
    : never
    : ReverseStringToTuple<ReverseString<`${A}`>> extends 
    [...ReverseStringToTuple<ReverseString<`${B}`>>,...infer R extends readonly any[]]
    ? R['length']    
    : ReverseStringToTuple<ReverseString<`${B}`>> extends 
    [...ReverseStringToTuple<ReverseString<`${A}`>>,...infer R extends readonly any[]]  
    ? `-${R['length'] }` extends `${infer N extends number}`
    ? N
    : never
    : never ;

    type Lesser<
        A extends number,
        B extends number> =
        `${Dif<A,B>}` extends `-${number}`
        ? true
        : false  ;

    type Greater<
        A extends number,
        B extends number> =
        `${Dif<B,A>}` extends `-${number}`
        ? true
        : false ;

type Comparator<
    A extends number, 
    B extends number> = 
    Greater<A,B> extends true
    ? Comparison.Greater
    : Lesser<A,B> extends true
    ? Comparison.Lower
    : Comparison.Equal  ;

Solution by justBadProgrammer #16151

// your answers
enum Comparison {
  Greater,
  Equal,
  Lower,
}
// A是否大于等于B
type Greater<A extends string, B extends string, Arr extends any[] = []> = `${Arr['length']}` extends B
  ? true
  : `${Arr['length']}` extends A
  ? false
  : Greater<A, B, [...Arr, 1]>
type Comparator<A extends number, B extends number> = A extends B ? Comparison.Equal
  : `${A}` extends `-${infer PosA}`
  ? `${B}` extends `-${infer PosB}`
  ? Greater<PosA, PosB> extends true ? Comparison.Lower : Comparison.Greater
  : Comparison.Lower
  : `${B}` extends `-${infer PosB}` ? Comparison.Greater
  : Greater<`${A}`, `${B}`> extends true ? Comparison.Greater : Comparison.Lower

Solution by fengchunqi #14621

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Comparator_ToNumber<A extends string, T extends any[] = []> = `${T['length']}` extends `${A}` ? T['length'] : Comparator_ToNumber<A, [...T, 1]>
type Comparator_ABS<A extends number> = `${A}` extends `-${infer U}` ? Comparator_ToNumber<U> : A
// A 正 B 负
// A 负 B 正
// 比较两个正整数,数组从 0 开始,如果先匹配 A ,说明 B 大,先匹配 B,说明 A 大
type Comparator_CORE<A extends number, B extends number, T extends any[] = []> =
  T['length'] extends A
    ? T['length'] extends B
      ? Comparison.Equal
      : Comparison.Lower
    : T['length'] extends B
      ? Comparison.Greater
      : Comparator_CORE<A, B, [...T, 1]>

type Comparator<A extends number, B extends number> =
  A extends Comparator_ABS<A>
    ? B extends Comparator_ABS<B>
      ? Comparator_CORE<A, B> // A 正 B 正
      : Comparison.Greater
    : B extends Comparator_ABS<B>
      ? Comparison.Lower
      : Comparator_CORE<Comparator_ABS<B>, Comparator_ABS<A>> // A 负 B 负

Solution by WongYAQi #12490

type Get<T, K> = K extends keyof T ? T[K] : never;

type Reverse<S> = S extends `${infer First}${infer Rest}`
  ? `${Reverse<Rest>}${First}`
  : '';

type ToUnion<S> = S extends `${infer First}${infer Rest}`
  ? First | ToUnion<Rest>
  : never;

type Digits = '0123456789';
type GenerateGreater<D> = D extends `${infer First}${infer Rest}`
  ? { [key in First]: ToUnion<Rest> } & GenerateGreater<Rest>
  : {};
type Greater = GenerateGreater<Digits>;

type InnerComparator<A, B> = A extends `${infer FirstA}${infer RestA}`
  ? B extends `${infer FirstB}${infer RestB}`
    ? FirstA extends FirstB
      ? InnerComparator<RestA, RestB>
      : RestA extends RestB
      ? FirstA extends Get<Greater, FirstB>
        ? Comparison.Greater
        : Comparison.Lower
      : InnerComparator<RestA, RestB>
    : Comparison.Greater
  : Comparison.Equal;

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Comparator<
  A extends number,
  B extends number,
  SA = `${A}`,
  SB = `${B}`,
> = SA extends `-${infer P}`
  ? SB extends `-${infer Q}`
    ? InnerComparator<Reverse<Q>, Reverse<P>>
    : Comparison.Lower
  : SB extends `-${string}`
  ? Comparison.Greater
  : InnerComparator<Reverse<SA>, Reverse<SB>>;

Solution by ryo-mf-fjt #11801

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type Comparator<X extends number, Y extends number> = {'<': Comparison.Lower, '=': Comparison.Equal, '>': Comparison.Greater}[CompareNumbers<`${X}`, `${Y}`>]

// Type to compare two numeric types X and Y and determine their relational order as '<', '=', or '>'.
type CompareNumbers<X extends string, Y extends string>
  = `${X}${Y}` extends `-${infer A}-${infer B}` ? CompareNumbers<B, A> // Handles comparison when both numbers are negative, invert the comparison order to compare their positive counterparts
  : X extends `-${any}` ? '<' // If X is negative and Y is not Y is greater
  : Y extends `-${any}` ? '>' // If Y is negative and X is not X is greater
  : `${X} ${Y}` extends `${infer A}e+${infer E} ${infer B}e+${infer F}` ? CompareInteger<E, F> extends '=' ? CompareNumbers<A, B> : CompareInteger<E, F>
  : X extends `${any}e+${any}` ? '>'
  : Y extends `${any}e+${any}` ? '<'
  : `${X} ${Y}` extends `${infer A}e-${infer E} ${infer B}e-${infer F}` ? CompareInteger<F, E> extends '=' ? CompareNumbers<A, B> : CompareInteger<F, E>
  : X extends `${any}e-${any}` ? '<'
  : Y extends `${any}e-${any}` ? '>'
  : `${X} ${Y}` extends `${infer A}.${infer C} ${infer B}.${infer D}` ? CompareInteger<A, B> extends '=' ? CompareFractional<C, D> : CompareInteger<A, B>
  : X extends `${infer A}.${any}` ? CompareInteger<A, Y> extends '=' ? '>' : CompareInteger<A, Y>
  : Y extends `${infer B}.${any}` ? CompareInteger<X, B> extends '=' ? '<' : CompareInteger<X, B>
  : CompareInteger<X, Y>

// Recursive type to compare integer strings and determine their order.
type CompareInteger<X extends string, Y extends string, PreviousComparison extends '<' | '=' | '>' = '='>
  = X extends Y ? PreviousComparison // If both strings are equal, return the previous comparison result
  : `${X} ${Y}` extends `${infer A}${infer C} ${infer B}${infer D}`
    ? CompareInteger<C, D,
        PreviousComparison extends '<' | '>' ? PreviousComparison // If difference has been found, Carry forward the first difference
        : A extends B ? '=' // If current digits are the same, skip to next
        : '0123456789' extends `${any}${A}${any}${B}${any}` ? '<' : '>'> // Compare digits lexicographically
  : X extends '' ? '<' : '>' // longer is greater

type CompareFractional<X extends string, Y extends string>
  = `${X} ${Y}` extends `${infer A}${infer C} ${infer B}${infer D}`
    ? A extends B ? CompareFractional<C, D> // If current digits are the same, skip to next
    : '0123456789' extends `${any}${A}${any}${B}${any}` ? '<' : '>' // Compare digits lexicographically
  : X extends '' ? '<' : '>' // longer is greater

Playground

Solution by teamchong #11540

type Comparator<A extends number | string, B extends number | string>
  = `${A}` extends `-${infer AbsA}`
    ? `${B}` extends `-${infer AbsB}`
      ? ComparePositives<AbsB, AbsA>
      : Comparison.Lower
    : `${B}` extends `-${number}`
      ? Comparison.Greater
      : ComparePositives<`${A}`, `${B}`>

// Compares two positive long numbers
type ComparePositives<A extends string, B extends string, ByLength = CompareByLength<A, B>>
  = ByLength extends Comparison.Equal
    ? CompareByDigits<A, B>
    : ByLength

// Compares two strings by length
type CompareByLength<A extends string, B extends string>
  = A extends `${infer AF}${infer AR}`
    ? B extends `${infer BF}${infer BR}`
      ? CompareByLength<AR, BR>
      : Comparison.Greater
    : B extends `${infer BF}${infer BR}`
      ? Comparison.Lower
      : Comparison.Equal

// Compares two positive long numbers of the same length
type CompareByDigits<A extends string, B extends string>
  = `${A}|${B}` extends `${infer AF}${infer AR}|${infer BF}${infer BR}`
    ? CompareDigits<AF, BF> extends Comparison.Equal
      ? CompareByDigits<AR, BR>
      : CompareDigits<AF, BF>
    : Comparison.Equal

// Compares two digits
type CompareDigits<A extends string, B extends string>
  = A extends B
    ? Comparison.Equal
    : '0123456789' extends `${string}${A}${string}${B}${string}`
      ? Comparison.Lower
      : Comparison.Greater

Examples:

// CompareByLength
CompareByLength<"1234", "567"> // Greater
CompareByLength<"123", "4567"> // Lower
CompareByLength<"123", "456">  // Equal
// CompareByDigits
CompareByDigits<"1234", "1224"> // Greater
CompareByDigits<"1234", "1244"> // Lower
CompareByDigits<"1234", "1234"> // Equal
// CompareDigits
CompareDigits<"5", "3"> // Greater
CompareDigits<"5", "7"> // Lower
CompareDigits<"5", "5"> // Equal

Extra tests:

Expect<Equal<Comparator<1234567891012345, 1234567891012345>, Comparison.Equal>>
Expect<Equal<Comparator<1234567891012345, 1234567891012346>, Comparison.Lower>>
Expect<Equal<Comparator<1234567891012345, 1234567891011234>, Comparison.Greater>>
// use strings for numbers greater than Number.MAX_SAFE_INTEGER (9007199254740991)
Expect<Equal<Comparator<'1234567890123456789', '1234567890123456790'>, Comparison.Lower>>,

Solution by Alexsey #11444

enum Comparison {
  Greater,
  Equal,
  Lower,
}

type ComparePositives<A extends string, B extends string, C extends 0[] = []>
  = A extends `${C['length']}`
    ? B extends `${C['length']}`
      ? Comparison.Equal
      : Comparison.Lower
    : B extends `${C['length']}`
      ? Comparison.Greater
      : ComparePositives<A, B, [...C, 0]>

type Comparator<A extends number, B extends number> =
  `${A}` extends `-${infer AbsA}`
    ? `${B}` extends `-${infer AbsB}`
      ? ComparePositives<AbsB, AbsA>
      : Comparison.Lower
    : `${B}` extends `-${number}`
      ? Comparison.Greater
      : ComparePositives<`${A}`, `${B}`>

Solution by Alexsey #11435

enum Comparison {
  Greater,
  Equal,
  Lower,
}
type GreaterThan<
  A extends number | string,
  B extends number | string,
  Arr extends unknown[] = []
  > = `${Arr['length']}` extends `${B}`
  ? `${Arr['length']}` extends `${A}`
  ? Comparison.Equal
  : Comparison.Greater
  : `${Arr['length']}` extends `${A}`
  ? Comparison.Lower
  : GreaterThan<A, B, [...Arr, unknown]>;

type Comparator<A extends number, B extends number> = `${A}` extends `-${infer N}` ?
  `${B}` extends `-${infer M}` ? N extends M ? Comparison.Equal : GreaterThan<N, M> extends Comparison.Greater ? Comparison.Lower : Comparison.Greater : Comparison.Lower
  : `${B}` extends `-${infer M}` ? Comparison.Greater : GreaterThan<A, B>

Solution by jackluson #9543