TypeScript 杂记十二 《Multiply》

Posted 左手121

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript 杂记十二 《Multiply》相关的知识,希望对你有一定的参考价值。

TypeScript 杂记十二 《Multiply》

Multiply

type T0 = Multiply<2, 3>; // '6'
type T1 = Multiply<3, "5">; // '15'
type T2 = Multiply<"4", 10>; // '40'
type T3 = Multiply<0, 16>; // '0'
type T4 = Multiply<"13", "21">; // '273'
type T5 = Multiply<"43423", 321543n>; // '13962361689'

思路

  • 只考虑正整数,输入验证
type Check<T extends string | number | bigint> = T extends number | bigint
  ? true
  : T extends `$infer L$infer R`
  ? L extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
    ? Check<R>
    : false
  : true;
  • A * B 可以理解为 B 个 A 相加
    • 考虑到可能存在 bigint,因此我们把每一位的数字单独拎出来计算,然后加起来
    • 例如 100 * 123
    • 先算 100 * 1 结果为 R
    • 再算 100 * 2 + R0 结果为新的 R
    • 最后算 100 * 3 + R0 结果为新的 R
    • 上边的 R0 表示的是 R 后边多加一位 0
  • 两个数字相加,我们采用两个数组相加(计算每一位),参考之前的内容 《SUM》我们不对加法进行说明
type HelperOne<
  A extends string[],
  B extends string,
  H extends unknown[] = [],
  R extends string[] = ["0"]
> = `$H["length"]` extends B
  ? R
  : HelperOne<A, B, [...H, unknown], Plus<A, R>>;

type Helper<
  A extends string[],
  B extends string,
  RR extends string[] = []
> = B extends `$infer L$infer R`
  ? Helper<A, R, Plus<[...RR, "0"], HelperOne<A, L>>>
  : RR;

结果

type Check<T extends string | number | bigint> = T extends number | bigint
  ? true
  : T extends `$infer L$infer R`
  ? L extends "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
    ? Check<R>
    : false
  : true;

type STA<
  T extends string,
  RR extends string[] = []
> = T extends `$infer L$infer R` ? STA<R, [...RR, L]> : RR;

type ATSHelper<T extends unknown[]> = T extends [infer L, ...infer R]
  ? L extends string
    ? `$L$ATSHelper<R>`
    : ""
  : "";

// '00010' 返回的是 '10'
// '000' 返回的是 '0'
type ATS<T extends unknown[]> = T extends ["0", ...infer R]
  ? ATS<R>
  : T extends []
  ? "0"
  : ATSHelper<T>;

type PlusOne<
  A extends string,
  B extends string,
  AA extends unknown[] = [],
  BA extends unknown[] = []
> = `$AA["length"]` extends A
  ? `$BA["length"]` extends B
    ? `$[...AA, ...BA]["length"] & number`
    : PlusOne<A, B, AA, [...BA, unknown]>
  : PlusOne<A, B, [...AA, unknown], BA>;

type PlusHelper<A, B, F extends boolean = false> = PlusOne<
  A extends string ? A : "0",
  PlusOne<B extends string ? B : "0", F extends true ? "1" : "0">
> extends `$infer _1$infer _2`
  ? _2 extends ""
    ? [false, _1]
    : [true, _2]
  : [false, "0"];

type Plus<
  A extends unknown[] = [],
  B extends unknown[] = [],
  R extends string[] = [],
  F extends boolean = false
> = A extends [...infer LA, infer RA]
  ? B extends [...infer LB, infer RB]
    ? Plus<LA, LB, [PlusHelper<RA, RB, F>[1], ...R], PlusHelper<RA, RB, F>[0]>
    : F extends true
    ? Plus<
        LA,
        [],
        [PlusHelper<RA, "1", false>[1], ...R],
        PlusHelper<RA, "1", false>[0]
      >
    : [...A, ...R]
  : B extends [...infer LB, infer RB]
  ? F extends true
    ? Plus<
        [],
        LB,
        [PlusHelper<"1", RB, false>[1], ...R],
        PlusHelper<"1", RB, false>[0]
      >
    : [...B, ...R]
  : F extends true
  ? ["1", ...R]
  : R;

type HelperOne<
  A extends string[],
  B extends string,
  H extends unknown[] = [],
  R extends string[] = ["0"]
> = `$H["length"]` extends B
  ? R
  : HelperOne<A, B, [...H, unknown], Plus<A, R>>;

type Helper<
  A extends string[],
  B extends string,
  RR extends string[] = []
> = B extends `$infer L$infer R`
  ? Helper<A, R, Plus<[...RR, "0"], HelperOne<A, L>>>
  : RR;

type Multiply<
  A extends string | number | bigint,
  B extends string | number | bigint
> = Check<A> extends true
  ? Check<B> extends true
    ? ATS<Helper<STA<`$A`>, `$B`>>
    : never
  : never;

以上是关于TypeScript 杂记十二 《Multiply》的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 杂记十二 《Multiply》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记一

TypeScript 杂记一