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
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',
}
Solution by teamchong #11577
Can display actual numbers instead of number
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