Skip to content

Sum

题目

Implement a type Sum<A, B> that summing two non-negative integers and returns the sum as a string. Numbers can be specified as a string, number, or bigint.

For example,

ts
type T0 = Sum<2, 3>; // '5'
type T1 = Sum<"13", "21">; // '34'
type T2 = Sum<"328", 7>; // '335'
type T3 = Sum<1_000_000_000_000n, "123">; // '1000000000123'

解答

ts
/**
 * @example
 * type Result = Sum<15, 8> // '23'
 *
 * type Step1A = NumberToArray<15> // [[0], [0, 0, 0, 0, 0]]
 * type Step1B = NumberToArray<8> // [[0, 0, 0, 0, 0, 0, 0, 0]]
 *
 * type Step2 = AddArray<Step1A, Step1B> // [[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
 *
 * type Step3 = StRegulateArrayNumber<Step2> // [[0, 0], [0, 0, 0]]
 *
 * type Step4 = RegulatedArrayNumberToStringNumber<Step3> // '23'
 */
type Sum<
  A extends string | number | bigint,
  B extends string | number | bigint
> = RegulatedArrayNumberToStringNumber<
  RegulateArrayNumber<AddArray<NumberToArray<A>, NumberToArray<B>>>
>;

type NumberToArray<
  T extends string | number | bigint,
  R extends 0[][] = []
> = `${T}` extends `${infer A extends number}${infer Rest}`
  ? NumberToArray<Rest, [...R, DigitToArray<A>]>
  : R;

type DigitToArray<T extends number, R extends 0[] = []> = R["length"] extends T
  ? R
  : DigitToArray<T, [...R, 0]>;

type AddArray<
  A extends 0[][],
  B extends 0[][],
  R extends 0[][] = []
> = A extends [...infer AR extends 0[][], infer AL extends 0[]]
  ? B extends [...infer BR extends 0[][], infer BL extends 0[]]
    ? AddArray<AR, BR, [[...AL, ...BL], ...R]>
    : [...A, ...R]
  : [...B, ...R];

type ArrayOf10 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

type RegulateArrayNumber<T extends 0[][], R extends 0[][] = []> = T extends []
  ? R
  : T extends [
      ...infer Rest extends 0[][],
      infer L2 extends 0[],
      infer L1 extends 0[]
    ]
  ? L1 extends [...ArrayOf10, ...infer More extends 0[]]
    ? RegulateArrayNumber<[...Rest, [...L2, 0]], [More, ...R]>
    : RegulateArrayNumber<[...Rest, L2], [L1, ...R]>
  : T[0] extends [...ArrayOf10, ...infer More extends 0[]]
  ? RegulateArrayNumber<[[0]], [More, ...R]>
  : RegulateArrayNumber<[], [T[0], ...R]>;

type RegulatedArrayNumberToStringNumber<
  T extends 0[][],
  R extends string = ""
> = T extends [infer A extends 0[], ...infer Rest extends 0[][]]
  ? RegulatedArrayNumberToStringNumber<Rest, `${R}${A["length"]}`>
  : R;

Released under the MIT License.