07561-extreme-subtract

Back

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

type RemoveZero<T> = T extends '0'
  ? T
  : T extends `${infer F}${infer R}` ? F extends '0' ? RemoveZero<R> : T : T

type Reverse<T> = T extends `${infer F}${infer R}`
  ? `${Reverse<R>}${F}`
  : ''

type NextNumber = { '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9' }

type PlusOne<T extends string> = T extends `${infer F}${infer R}`
  ? F extends '9'
    ? `0${PlusOne<R>}`
    : `${NextNumber[F & keyof NextNumber]}${R}`
  : '1'

type ReversedSubtract<
  M extends string,
  S extends string,
> = `${M}` extends `${infer F1}${infer R1}`
  ? `${S}` extends `${infer F2}${infer R2}`
    ? F1 extends F2
      ? `0${ReversedSubtract<R1, R2>}`
      : F2 extends '0'
        ? `${F1}${ReversedSubtract<R1, R2>}`
        : ReversedSubtract<PlusOne<M>, PlusOne<S>>
    : ''
  : `${S}` extends `${infer _}${infer _}` ? never : M

// M => minuend, S => subtrahend
type Subtract<
  M extends number,
  S extends number,
> = ParseInt<RemoveZero<Reverse<ReversedSubtract<Reverse<`${M}`>, Reverse<`${S}`>>>>>

Solution by Heonys #32510

type Subtract<
  Minuend extends number,
  Subtrahend extends number,
  C extends 0[] = [],
  D extends 0[] = []
> = C["length"] extends Minuend
  ? D["length"] extends 0
    ? Minuend extends Subtrahend
      ? 0
      : never
    : D["length"]
  : C["length"] extends Subtrahend
  ? Subtract<Minuend, Subtrahend, [0, ...C], [0, ...D]>
  : D["length"] extends 0
  ? Subtract<Minuend, Subtrahend, [0, ...C], D>
  : Subtract<Minuend, Subtrahend, [0, ...C], [0, ...D]>;

Solution by vangie #32340

type NTuple<N extends number, Arr extends any[] = []> = Arr extends {
  length: N;
}
  ? Arr
  : NTuple<N, [...Arr, any]>;

type Substract<N1 extends number, N2 extends number> = NTuple<N1> extends [
  ...infer R,
  ...NTuple<N2>
]
  ? R["length"]
  : never;

Solution by slemchik03 #27660

type MakeCounter<N extends number, _Result extends 1[] = []> = _Result[`length`] extends N ? _Result : MakeCounter<N, [..._Result, 1]>;
type Pop<T extends any[]> = T extends [...infer R, any] ? R : [];
type SimpleCounterMinu<C1 extends any[], C2 extends any[]> = C1 extends [] ?
  (C2 extends [] ? 0 : never) : //0-0 or Negative
  (C2 extends [] ? C1[`length`] /*return*/ : SimpleCounterMinu<Pop<C1>, Pop<C2>>);

type Subtract<M extends number, S extends number> = SimpleCounterMinu<MakeCounter<M>, MakeCounter<S>>;

Solution by E-uler #25875

type NumberToArray<T extends number, Result extends 0[] = []> = Result['length'] extends T 
? Result
: NumberToArray<T, [...Result, 0]>

type Subtract<
  T extends number, 
  U extends number, 
  TCounter extends 0[] = [], 
  UCounter extends 0[] = []
> = TCounter['length'] extends T 
? TCounter extends [...UCounter, ...infer AfterSubtract]
  ? AfterSubtract['length']
  : never
: Subtract<T, U, NumberToArray<T>, NumberToArray<U>>

Solution by NeylonR #24995

type Subtract<T extends number,U extends number,N extends 0[] = [],V extends 0[] = []> = 
T extends N['length']
? T extends U
  ? 0
  : V['length'] extends 0
  ? never
  : N extends [...V, ...infer L]
  ? L['length']
  : 0
: U extends N['length']
? Subtract<T, U, [...N, 0], N>
: Subtract<T, U, [...N, 0], V>

Solution by TKBnice #24554

type BuildTuple<T extends number, _TP extends unknown[] = []> = 
  _TP['length'] extends T
  ? _TP
  : BuildTuple<T, [..._TP, unknown]>
  
// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = 
  BuildTuple<M> extends [...BuildTuple<S>, ...infer Rest]
  ? Rest['length']
  : never

playground

Finally! Last challenge completed!

I don't know why this is marked as extreme, it's so simple...

Solution by zhaoyao91 #23451

type NTuple<N extends number, C extends unknown[]=[]>=C['length'] extends N ? C : NTuple<N, [...C, 0]>;
type Subtract<M extends number, S extends number> = NTuple<M> extends [...NTuple<S> , ...infer Rest] ? Rest['length'] : never;

Solution by Karamuto #22360

// M => minuend, S => subtrahend
type CreateTuple<
  N extends number,
  Tuple extends 1[] = []
> = Tuple["length"] extends N ? Tuple : CreateTuple<N, [...Tuple, 1]>;
type Subtract<M extends number, S extends number> = CreateTuple<M> extends [
  ...CreateTuple<S>,
  ...infer Rest
]
  ? Rest["length"]
  : never;

Solution by wubetter #21037

// Create array of N length
type NArray<N extends number, A extends any[]= []> = A['length'] extends N ? A : NArray<N, [...A, never]>;

type Reduce<M extends any[], S extends any[]> = 
  S extends [infer S1, ...infer SR] 
  ? M extends [infer M1, ...infer MR]
    ? Reduce<MR, SR>
    : never
  : M['length'];

// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = Reduce<NArray<M>, NArray<S>>

Solution by mdakram28 #20678

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

type NumToArr<Num extends number, Res extends any[] = []> = Res['length'] extends Num ? Res : NumToArr<Num, [1, ...Res]>

type Pop<Arr extends any[], P extends number, Count extends any[] = []> = Arr extends [...infer Head, infer Tail] 
  ? Count['length'] extends P
    ? Arr : Pop<Head, P, [...Count, 1]>
  : GreaterThan<P, Count['length']> extends true ? never : []

type Subtract<M extends number, S extends number, Arr1 extends any[] = NumToArr<M>> = Pop<Arr1, S>['length']

Solution by Zhukov87 #19994

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 Subtract<
  M extends number,
  S extends number
> = `${M}` extends `${number}${number}${number}${number}`
  ? never
  : ArrayWithLength<M> extends [...ArrayWithLength<S>, ...infer R]
  ? R['length']
  : never

Solution by theoolee #19897

// your answers
type Digits =
{
  '0':[],
  '1':[0],
  '2':[0,0],
  '3':[0,0,0],
  '4':[0,0,0,0],
  '5':[0,0,0,0,0],
  '6':[0,0,0,0,0,0],
  '7':[0,0,0,0,0,0,0],
  '8':[0,0,0,0,0,0,0,0],
  '9':[0,0,0,0,0,0,0,0,0],
} ;

type _10=[0,0,0,0,0,0,0,0,0,0]  ;

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

type Multiply<
    A extends readonly any[],
    B extends readonly any[]> =
    A extends readonly [infer R,...infer U extends readonly any[]]
    ? [...B,...Multiply<U,B>]
    : []  ;

type ReversedStringToTuple<
    Str extends string> =
    Str extends `${infer R extends keyof Digits}${infer U extends string}`
    ? [...Digits[R],...Multiply<_10,ReversedStringToTuple<U>>]
    : []  ;
   
type Subtract<
    M extends number, 
    S extends number> =
    ReversedStringToTuple<ReverseString<`${M}`>> extends 
    readonly [...ReversedStringToTuple<ReverseString<`${S}`>>,...infer U extends readonly any[]]
    ? U['length']
    : never ;

Solution by justBadProgrammer #17148

// 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 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 PlusOne<T extends number, Result extends 0[] = NumberToTuple<T>> = [...Result, 0]['length'] & number

type Minus<M extends number, N extends number, Result extends number = 0> = M extends N
  ? Result
  : Minus<M, PlusOne<N>, PlusOne<Result>>

// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = GT<S, M> extends true
  ? never
  : Minus<M, S>

Solution by humandetail #16699

/*
Return if a number is smaller than another number
Input: 2,1
Output: true
*/
type IsSmallerThan<T extends number, U extends number, US extends number[] = []> = 
US['length'] extends T 
  ? US['length'] extends U 
  ? true 
  : false 
  :US['length'] extends U 
  ? true
: IsSmallerThan<T, U, [...US, 1]>

/*
Fills an array with ones until the length of the array is the same as the provided number
Input: 5
Output: [1,1,1,1,1]
*/
type FillArray<T extends number, Acc extends 1[] =[]> = Acc['length'] extends T ? Acc : FillArray<T, [...Acc,1]>  

/*
Idea (3, 1): Fill an array to the length of the lower number (1 => [1]), then add an temporary array and fill it until the length of the combined arrays [1] and temp[] is [1,1,1] (3)

Solution 1:
Let Typescript do the work by infering via a Rest parameter, and if the condition is meet, return the length of the infered Array
*/
type Subtract<M extends number, S extends number> = FillArray<M> extends [...FillArray<S>, ...infer Rest] ? Rest['length'] : never

/*
Solution 2:
Use an accumulator that stores the current diff between T and U. Fill that accumulator until the union of accumulator and the filled array of the smaller number sums up to the higher number
*/
type Subtract<M extends number, S extends number, MA extends number[]= FillArray<M>, SA extends number[] = FillArray<S>, Temp extends number[] =[]> = IsSmallerThan<M,S> extends false ? never:[...SA, ...Temp]['length'] extends M ? Temp['length'] : Subtract<M,S, MA,SA, [...Temp,1]>

Solution by JohannesSchwegler #16386

// your answers
type Subtract<M extends number, S extends number, P extends unknown[] = [], R extends unknown[] = []> = P['length'] extends S
  ? (
    [...P, ...R]['length'] extends M ? R['length'] : Subtract<M, S, P, [...R, 1]>
  )
  : (
    P['length'] extends M ? never : Subtract<M, S, [...P, 1], R>
  )

Solution by fengchunqi #14953

// your answers
type Rang<T extends Number = 0, P extends 1[] = []> =
  P['length'] extends T ?
    P : Rang<T, [1, ...P]>
type Shift<T extends 1[]> = T extends [infer F, ...infer Rest] ? Rest : []
type Subtract<M extends number, S extends number, L extends 1[] = Rang<M>, R extends 1[] = Rang<S>> = 
  L['length'] extends 0
    ? R['length'] extends 0
      ? 0
      : never
    : R['length'] extends 0
      ? L['length']
      : Subtract<M, S, Shift<L>, Shift<R>>

Solution by Sliect #14578

type Subtract<M extends number, S extends number> = M extends -1
  ? never
  : S extends 0
  ? M
  : Subtract<MinusOne<M>, MinusOne<S>>;

type MinusOne<T extends number> = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9][T];

Solution by fardolieri #14186

type Arr<X extends number, A extends unknown[]> = A['length'] extends X ? A : Arr<X, [A['length'], ...A]>

type Subtract<M extends number, S extends number> = Exclude<[never, ...Arr<M, []>][S], undefined>

Solution by krscott #13579


type Number<T extends number> = _while<T, []>

type _while<T extends number, L extends NumberLike> = 
  Equal<L["length"], T> extends true
    ? L
    : _while<T, [...L, 0]>

type Numbering<T extends NumberLike> = T["length"]

type NumberLike = Array<any>
type Minus<T extends NumberLike, K extends NumberLike> = 
  T extends [...K, ...infer I] ? I : never

type Subtract<M extends number, S extends number> = Numbering<Minus<Number<M>, Number<S>>>

Solution by DrLee-lihr #11989

// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number,
  Diff extends 1[] = [],              // from S to M - 1
  Count extends 1[] = [],             // from 0 to M - 1
  N extends number = Count['length'],
  Started extends number = Diff extends [] ? (N extends S ? S : never) : S
> =
  N extends M ? (         // stop when N = M
    S extends Started ? (
      Diff['length']      // return length of Diff
    ) : never             // when M < S
  ) : S extends Started ? (
    Subtract<M, S, [...Diff, 1], [...Count, 1]>
  ) : Subtract<M, S, Diff, [...Count, 1]>

Not an answer to this Question, but another version for Subtract

// This version doesn't use Tuple
type Subtract2<M extends string | number | bigint, S extends string | number | bigint> =
  `${M}${S}` extends `-${infer NegM}-${infer NegS}` ? (
    SubtractPositive<NegS, NegM>
  ) : `${M}` extends `-${infer NegM}` ? (
    `-${Sum<NegM, `${S}`>}`
  ) : `${S}` extends `-${infer NegS}` ? (
    Sum<`${M}`, NegS>
  ) : SubtractPositive<`${M}`, `${S}`> extends infer Result ? (
    Result extends `~${string}` ? (
      `-${SubtractPositive<`${S}`, `${M}`>}`
    ) : Result
  ) : never

type SubtractPositive<M extends string, S extends string> =
  `${ParseLast<`${M}`>}|${ParseLast<`${S}`>}` extends `${infer LeadingA}|${infer LastA}|${infer LeadingB}|${infer LastB}` ? (
    CalculateMap[`${LastA}-${LastB}` & keyof CalculateMap] extends `${infer Forward}${infer Digit}` ? (
      `${RemoveLeadingZero<SubtractPositive<LeadingA, Sum<LeadingB, Forward>>>}${Digit}`
    ) : 2
  ) : `${RemoveLeadingZero<M>}${RemoveLeadingZero<S>}` extends '' ? (
    ''
  ) : `~`

type Sum<A extends string | number | bigint, B extends string | number | bigint> =
  `${ParseLast<`${A}`>}|${ParseLast<`${B}`>}` extends `${infer LeadingA}|${infer LastA}|${infer LeadingB}|${infer LastB}` ? (
    CalculateMap[`${LastA}+${LastB}` & keyof CalculateMap] extends `${infer Forward}${infer Digit}` ? (
      `${RemoveLeadingZero<Sum<Sum<LeadingA, LeadingB>, Forward>>}${Digit}`
    ) : 3
  ) : `${A}${B}` // when either is empty

type RemoveLeadingZero<T extends string> = T extends `0${infer Rest}` ? RemoveLeadingZero<Rest> : T

type ParseLast<T extends string, Leading extends string = ''> =
  T extends `${infer First}${infer Rest}` ? (
    Rest extends '' ? (
      `${Leading}|${First}`
    ) : ParseLast<Rest, `${Leading}${First}`>
  ) : Leading extends '' ? (
    ''  // T and Leading are empty
  ) : `${Leading}|${T}`

type CalculateMap = {
  '0+0': '00', '0+1': '01', '0+2': '02', '0+3': '03', '0+4': '04', '0+5': '05', '0+6': '06', '0+7': '07', '0+8': '08', '0+9': '09',
  '1+0': '01', '1+1': '02', '1+2': '03', '1+3': '04', '1+4': '05', '1+5': '06', '1+6': '07', '1+7': '08', '1+8': '09', '1+9': '10',
  '2+0': '02', '2+1': '03', '2+2': '04', '2+3': '05', '2+4': '06', '2+5': '07', '2+6': '08', '2+7': '09', '2+8': '10', '2+9': '11',
  '3+0': '03', '3+1': '04', '3+2': '05', '3+3': '06', '3+4': '07', '3+5': '08', '3+6': '09', '3+7': '10', '3+8': '11', '3+9': '12',
  '4+0': '04', '4+1': '05', '4+2': '06', '4+3': '07', '4+4': '08', '4+5': '09', '4+6': '10', '4+7': '11', '4+8': '12', '4+9': '13',
  '5+0': '05', '5+1': '06', '5+2': '07', '5+3': '08', '5+4': '09', '5+5': '10', '5+6': '11', '5+7': '12', '5+8': '13', '5+9': '14',
  '6+0': '06', '6+1': '07', '6+2': '08', '6+3': '09', '6+4': '10', '6+5': '11', '6+6': '12', '6+7': '13', '6+8': '14', '6+9': '15',
  '7+0': '07', '7+1': '08', '7+2': '09', '7+3': '10', '7+4': '11', '7+5': '12', '7+6': '13', '7+7': '14', '7+8': '15', '7+9': '16',
  '8+0': '08', '8+1': '09', '8+2': '10', '8+3': '11', '8+4': '12', '8+5': '13', '8+6': '14', '8+7': '15', '8+8': '16', '8+9': '17',
  '9+0': '09', '9+1': '10', '9+2': '11', '9+3': '12', '9+4': '13', '9+5': '14', '9+6': '15', '9+7': '16', '9+8': '17', '9+9': '18',
  '0-0': '00', '0-1': '19', '0-2': '18', '0-3': '17', '0-4': '16', '0-5': '15', '0-6': '14', '0-7': '13', '0-8': '12', '0-9': '11',
  '1-0': '01', '1-1': '00', '1-2': '19', '1-3': '18', '1-4': '17', '1-5': '16', '1-6': '15', '1-7': '14', '1-8': '13', '1-9': '12',
  '2-0': '02', '2-1': '01', '2-2': '00', '2-3': '19', '2-4': '18', '2-5': '17', '2-6': '16', '2-7': '15', '2-8': '14', '2-9': '13',
  '3-0': '03', '3-1': '02', '3-2': '01', '3-3': '00', '3-4': '19', '3-5': '18', '3-6': '17', '3-7': '16', '3-8': '15', '3-9': '14',
  '4-0': '04', '4-1': '03', '4-2': '02', '4-3': '01', '4-4': '00', '4-5': '19', '4-6': '18', '4-7': '17', '4-8': '16', '4-9': '15',
  '5-0': '05', '5-1': '04', '5-2': '03', '5-3': '02', '5-4': '01', '5-5': '00', '5-6': '19', '5-7': '18', '5-8': '17', '5-9': '16',
  '6-0': '06', '6-1': '05', '6-2': '04', '6-3': '03', '6-4': '02', '6-5': '01', '6-6': '00', '6-7': '19', '6-8': '18', '6-9': '17',
  '7-0': '07', '7-1': '06', '7-2': '05', '7-3': '04', '7-4': '03', '7-5': '02', '7-6': '01', '7-7': '00', '7-8': '19', '7-9': '18',
  '8-0': '08', '8-1': '07', '8-2': '06', '8-3': '05', '8-4': '04', '8-5': '03', '8-6': '02', '8-7': '01', '8-8': '00', '8-9': '19',
  '9-0': '09', '9-1': '08', '9-2': '07', '9-3': '07', '9-4': '05', '9-5': '04', '9-6': '03', '9-7': '02', '9-8': '01', '9-9': '00',
}

Playground

Solution by teamchong #11577

Can display actual numbers instead of number

image

How is work

type Tuple<T, Res extends 1[] = []> = 0 extends 1 ? never : Res['length'] extends T ? Res : Tuple<T, [...Res, 1]>;

type Subtract<M extends number, S extends number> = Tuple<M> extends [...Tuple<S>, ...infer Rest] ? Rest['length'] : never

Solution by ProsperBao #11216

type CreateArr<T extends number , Res extends any[] = []> = Res['length'] extends T ? Res: CreateArr<T,[...Res,unknown]>

type Subtract<M extends number, S extends number> = CreateArr<M>  extends [...start:CreateArr<S>,...end: infer Res] ? Res['length'] : never

Solution by EGyoung #10243

type Length<T extends any[]> = T['length']
type ToArray<T extends number, R extends any[] = []> = Length<R> extends T ? R : ToArray<T, [...R, any]>
type Subtract<M extends number, S extends number> = ToArray<M> extends [...ToArray<S>, ...infer Rest] ? Length<Rest> : never

Solution by xuemanchi #9157

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

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 = [...N9, any];

type DigitToTuple<N, L = N extends string | number ? `${N}` : ''> = L extends `${N1['length']}` ? N1 
    : L extends `2`? N2 
    : L extends `3`? N3 
    : L extends `4`? N4 
    : L extends `5`? N5 
    : L extends `6`? N6 
    : L extends `7`? N7 
    : L extends `8`? N8 
    : L extends `9`? N9 
    : [];

type ToTuple<T extends bigint | string | number, S = `${T}`> = S extends `${infer F}${infer O}` ? [F, ...ToTuple<O>] : [];

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

type TupleLast<T extends any[]> = T extends [...any, infer L] ? L : never;

type Comparator<L extends any[], R extends any[]> = L extends [...R, ...infer O] ? O['length'] extends 0 ? 0 : 1 : -1;

type LowSub<M extends any[], S extends any[]> = 
  M extends [...S, ...infer N] ? [N['length'], []] 
  : [...N10, ...M] extends [...S, ...infer N] ? [N['length'],[any]]
  : never;

type OrderSub<M extends any[], S extends any[], R extends any[] = [], P extends any[] = [], ML extends any[] =DigitToTuple<TupleLast<M>>, SL extends any [] = [...DigitToTuple<TupleLast<S>>, ...P] > = 
  M extends [] ? ( P extends [] ? R:never)
  : S extends []? R
  : LowSub<ML, SL> extends [infer R1, infer N] ? OrderSub<TupleTail<M>, TupleTail<S>, [R1,...R], (N extends any[]?N:[])>
  :never;

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

type Result<T extends any[], B extends any[] = [any], R extends any[]=[]> = T extends [...infer F, infer L] ? Result<F, TupleRepeat<B, 10>, [...R, ...TupleRepeat<B, L>]> : R['length'];

// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number, Mu extends any[] = ToTuple<M>, Su extends any[] = ToTuple<S>> = 
  Comparator<GetLenTuple<Mu['length']>, GetLenTuple<Su['length']>> extends -1 ? never 
  :Result<OrderSub<Mu, Su>>;

Solution by venusliang #8044

// your answers
type NumberToTupleBase<T extends string, R extends any[] = []> = `${T}` extends `${number}`
? `${T}` extends `${R['length']}`
  ? R
  : NumberToTupleBase<T, [...R, unknown]>
: []

type Expand10<T extends any[]> = [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T]

type ConstructTuple<S extends number | string, Res extends any[] = []> = `${S}` extends `${infer L}${infer R}`
? ConstructTuple<R, [...Expand10<Res>, ...NumberToTupleBase<L>]>
: Res

type Subtract<M extends number, S extends number> = ConstructTuple<M> extends [...ConstructTuple<S>, ...infer R] ? R['length'] : never

Solution by ch3cknull #7963

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

// M => minuend, S => subtrahend
type Subtract<M extends number, S extends number> = ConstructTuple<M> extends [...subtrahend: ConstructTuple<S>, ...rest: infer Rest] ? Rest["length"] : never

Solution by LoTwT #7680

θ™½η„Άδ½†ζ˜―γ€‚γ€‚γ€‚ζ„Ÿθ§‰

// @ts-expect-error
  Expect<Equal<ExtremeSubtract<1000, 999>, 1>>

不应θ―₯ζ˜―ζœŸζœ›ζŠ₯错吧。。。

// your answers
type EqualOrGreaterThan<F extends number, S extends number, CountArr extends Array<unknown> = []> = 
  F extends S
  ? true
  : CountArr['length'] extends F
    ? false
    : CountArr['length'] extends S
      ? true
      : EqualOrGreaterThan<F, S, [...CountArr, unknown]>

type BuildTuple<N extends number, CountArr extends Array<unknown> = []> = 
  CountArr['length'] extends N ? CountArr : BuildTuple<N, [...CountArr, unknown]>

type SubtractHelper<M extends number, S extends number> = 
  BuildTuple<M> extends [...infer Rest, ...BuildTuple<S>] ? Rest['length'] : 0
// M => minuend, S => subtrahend
type ExtremeSubtract < M extends number, S extends number > =
  EqualOrGreaterThan < M, S > extends true
    ? SubtractHelper<M, S>
    : never 


Solution by HongxuanG #7669