UNPKG

type-samurai

Version:

Advanced utility types for Typescript

133 lines (128 loc) 3.73 kB
import { IsEqual } from "./equal"; import { If } from "./if"; import { LastCharacter } from "./last-character"; import { IsNever } from "./never"; import { Abs, IfNegative, Negate, ParseNumber } from "./number"; import { Push } from "./push"; import { RemoveLeading } from "./remove-leading"; import { Repeat } from "./repeat"; import { ReturnItselfIfNotExtends } from "./return-itself-if-extends"; import { IsEmptyString } from "./string"; import { Stringify } from "./stringify"; import { Sum, _Sum } from "./sum"; type MultiplicationMap = { 0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 2: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]; 3: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]; 4: [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]; 5: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]; 6: [0, 6, 12, 18, 24, 30, 36, 42, 48, 54]; 7: [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]; 8: [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]; 9: [0, 9, 18, 27, 36, 45, 54, 63, 72, 81]; }; type _MultSingle< Num1 extends string, DigitOfNum2 extends keyof MultiplicationMap, Carry extends number = 0, Result extends string = "" > = IsEmptyString<Num1> extends true ? ReturnItselfIfNotExtends<RemoveLeading<`${Carry}${Result}`, "0">, "", "0"> : IsEqual<Num1, 0> extends true ? "0" : IsEqual<DigitOfNum2, 0> extends true ? "0" : LastCharacter<Num1, { includeRest: true }> extends [ infer Num1LastCharacter extends string, infer Num1Rest extends string ] ? Stringify< Sum< MultiplicationMap[DigitOfNum2][ParseNumber<Num1LastCharacter> & keyof MultiplicationMap[DigitOfNum2]], Carry > > extends infer Multiplied extends string ? LastCharacter<Multiplied, { includeRest: true }> extends [ infer MultipliedLastDigit extends string, infer MultipliedRest extends string ] ? _MultSingle< Num1Rest, DigitOfNum2, If< IsNever<ParseNumber<MultipliedRest>>, 0, ParseNumber<MultipliedRest> >, `${MultipliedLastDigit}${Result}` > : never : never : never; type _Mult< Num1 extends string, Num2 extends string, Result extends string = "", Iteration extends unknown[] = [] > = IsEmptyString<Num2> extends true ? Result : LastCharacter<Num2, { includeRest: true }> extends [ infer Num2LastCharacter extends string, infer Num2Rest extends string ] ? ParseNumber<Num2LastCharacter> extends infer Num2Digit extends keyof MultiplicationMap ? _Mult< Num1, Num2Rest, Stringify< _Sum< Result, ReturnItselfIfNotExtends< RemoveLeading< `${_MultSingle<Num1, Num2Digit>}${Repeat< "0", Iteration["length"] >}`, "0" >, "", "0" > > >, Push<Iteration, unknown> > : never : Result; /** * Accepts tow integers and returns their multiplication. Range: `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]` * @example * ```ts * // 0 * type Case1 = Mult<10, 0> * // 24 * type Case2 = Mult<4, 6> * // -24 * type Case3 = Mult<-4, 6> * // 24 * type Case4 = Mult<-4, -6> * ``` */ export type Mult<Num1 extends number, Num2 extends number> = IsEqual< Num1, 0 > extends true ? 0 : IsEqual<Num2, 0> extends true ? 0 : ParseNumber< _Mult<Stringify<Abs<Num1>>, Stringify<Abs<Num2>>> > extends infer Result extends number ? IfNegative< Num1, IfNegative<Num2, Result, Negate<Result>>, IfNegative<Num2, Negate<Result>, Result> > : never;