27133-medium-square

Back

can not pass: Expect<Equal<Square<100>, 10000>>, Expect<Equal<Square<-50>, 2500>>, because Type instantiation is excessively deep and possibly infinite... need to enhance ...

  type AppendEveryLine<Ret extends any[][]> = {
    [P in keyof Ret]: [...Ret[0], 1];
  };

  type ExpandMatrix<T extends any[][]> = T['length'] extends 0
    ? [[1]]
    : AppendEveryLine<[...T, T[0]]>;

  type FlattenOnce<T extends any[][] = []> = T extends [
    infer First extends any[],
    ...infer Rest extends any[][]
  ]
    ? [...First, ...FlattenOnce<Rest>]
    : [];

  type Square<
    _N extends number,
    N extends number = `${_N}` extends `-${infer N extends number}` ? N : _N,
    Ret extends any[] = [],
    Temp extends any[][] = []
  > = N extends Temp['length']
    ? FlattenOnce<Temp>['length']
    : Square<N, N, [...Ret, 1], ExpandMatrix<Temp>>;

Solution by sunupupup #33482

type SquareAbs<N, C extends 1[] = [], R extends 1[] = []> = C['length'] extends N
  ? R['length']
  : SquareAbs<N, [...C, 1], [...R, ...C, ...C, 1]>;

type Square<N extends number> = N extends -100 | 100
  ? 10000
  : SquareAbs<`${N}` extends `-${infer V extends number}` ? V : N>;

Solution by alexandroppolus #33238

// your answers
// Utils
type As<Input, T> = Input extends T ? Input : never
type MakeTuple<T, Length extends number, Result extends T[] = []> = Result['length'] extends Length 
  ? Result
  : MakeTuple<T, Length, [...Result, T]>
type Shifted<T extends any[]> = T extends [any, ...infer Rest extends any[]] ? Rest : T
type Popped<T extends any[]> = T extends [...infer Rest extends any[], any] ? Rest : T
type PadLeft<SplittedNum extends number[], Padding1 extends number, Padding2 extends number> = [...MakeTuple<0, Padding1>, ...MakeTuple<0, Padding2>, ...SplittedNum]


// Input
// Split digits and reverse (ex: 123 -> [3, 2, 1])
type ToSplittedNum<S extends string | number, Result extends number[] = []> = `${S}` extends infer N extends string
  ? N extends `${infer C extends number}${infer Rest}`
    ? ToSplittedNum<Rest, [C, ...Result]>
    : Result extends number[] 
      ? Result 
      : never
  : never

// Calc
// 9x9 Multiplication Table
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
type MultiplyTwoDigits<D1 extends Digit, D2 extends Digit, Loop extends 0[] = [], Result extends 0[] = []> = Loop['length'] extends D2 
  ? ToSplittedNum<Result['length']>
  : MultiplyTwoDigits<D1, D2, [...Loop, 0], As<[...Result, ...MakeTuple<0, D1>], 0[]>>
type DigitMultiplicationTableKey = `${Digit}x${Digit}`
type DigitMultiplicationTable = {
  [K in DigitMultiplicationTableKey]: K extends `${infer D1 extends Digit}x${infer D2 extends Digit}`
    ? MultiplyTwoDigits<D1, D2>
    : never
}

// Addition
type AddDigits<Digits extends number[], Result extends 0[] = []> = Digits extends [infer D extends number, ...infer Rest extends number[]]
  ? MakeTuple<0, D> extends infer Temp extends 0[] 
    ? AddDigits<Rest, [...Result, ...Temp]>
    : never
  : ToSplittedNum<Result['length']>
type AddTwoSplittedNums<
  SplittedN1 extends number[],
  SplittedN2 extends number[],
  Carry extends 0 | 1 = 0,
  Result extends number[] = [],
  NextSplittedN1 extends number[] = Shifted<SplittedN1>,
  NextSplittedN2 extends number[] = Shifted<SplittedN2>,
  DigitResult extends number[] = AddDigits<[Carry, SplittedN1[0], SplittedN2[0]]>,
> = [SplittedN1, SplittedN2, Carry] extends [[0], [0], 0]
  ? Result extends number[]
    ? Result 
    : never
  : AddTwoSplittedNums<
      (NextSplittedN1 extends [] ? [0] : NextSplittedN1),
      (NextSplittedN2 extends [] ? [0] : NextSplittedN2),
      (DigitResult['length'] extends 1 ? 0 : 1),
      [...Result, DigitResult[0]]
    >

// Two Levels Loop walk through each digits of two numbers
type Multiply_Advanced_Level1_Loop<
  SplittedN1 extends number[], 
  SplittedN2 extends number[],
  Result extends number[] = [0],
  P1 extends number = Popped<SplittedN1>['length']
> = SplittedN1 extends [...infer Rest extends number[], infer D1 extends Digit]
  ? Multiply_Advanced_Level1_Loop<
      Rest,
      SplittedN2,
      AddTwoSplittedNums<Result, Multiply_Advanced_Level2_Loop<SplittedN2, D1, P1>> extends infer Temp extends number[] ? Temp : never
    >
  : Result
type Multiply_Advanced_Level2_Loop_Calc<
  D1 extends number,
  P1 extends number,
  D2 extends number,
  P2 extends number,
> = PadLeft<Multiply_Simple<D1, D2>, P1, P2> extends infer Result extends number[]
  ? Result
  : never
type Multiply_Advanced_Level2_Loop<
  SplittedN2 extends number[], 
  D1 extends number, 
  P1 extends number, 
  Result extends number[] = [0],
  P2 extends number = Popped<SplittedN2>['length']
> = SplittedN2 extends [...infer Rest extends number[], infer D2 extends number]
  ? Multiply_Advanced_Level2_Loop<
      Rest,
      D1,
      P1,
      AddTwoSplittedNums<Result, Multiply_Advanced_Level2_Loop_Calc<D1, P1, D2, P2>>
    >
  : Result

// Output
type ToOutputString<SplittedNum extends number[]> = SplittedNum extends [infer C extends number, ...infer Rest extends number[]]
  ? `${ToOutputNumber<Rest>}${C}`
  : ''
type ToNumber<S extends string> = S extends `${infer N extends number}` ? N : S
type ToOutputNumber<SplittedNum extends number[]> = ToNumber<ToOutputString<SplittedNum>>

// Multiply
// Directly map from 9x9 Multiplication Table
type Multiply_Simple<N1 extends number, N2 extends number> = `${N1}x${N2}` extends infer K extends DigitMultiplicationTableKey 
  ? DigitMultiplicationTable[K]
  : never
// Calculate every digit and sum
type Multiply_Advanced<N1 extends number, N2 extends number> = Multiply_Advanced_Level1_Loop<ToSplittedNum<N1>, ToSplittedNum<N2>>

type Multiply<N1 extends number, N2 extends number> = ToOutputNumber<
  [ToSplittedNum<N1>['length'], ToSplittedNum<N2>['length']] extends [1, 1]
    ? Multiply_Simple<N1, N2>
    : Multiply_Advanced<N1, N2>
>

type Abs<N extends number> = `${N}` extends `-${infer _N extends number}` ? _N : N

type Square<N extends number> = Multiply<Abs<N>, Abs<N>>

Solution by DevilTea #33227

// Generates array from 0 to N (inclusive)
type GenerateArr<N extends number, Acc extends number[] = []> = Acc['length'] extends N
  ? Acc
  : GenerateArr<N, [...Acc, Acc['length']]>

type FlattenArr<A extends unknown[]> = A extends [infer X extends number[], ...infer R] ? [...X, ...FlattenArr<R>] : A;

type AbsoluteSquare<N extends number, Acc extends unknown[] = []> = 
  Acc['length'] extends N 
    ? FlattenArr<Acc>['length']
    : AbsoluteSquare<N, [...Acc, GenerateArr<N>]>

type Square<N extends number> = `${N}` extends `-${infer NonNegNum extends number}` 
  ? AbsoluteSquare<NonNegNum> 
  : AbsoluteSquare<N>

Solution by keyurparalkar #32648

type PadList<N extends number, C extends any[] = []> = C["length"] extends N
  ? C
  : PadList<N, [...C, 0]>;

type Absolute<T extends number> = `${T}` extends `-${infer U extends number}`
  ? U
  : T;

type Square<
  N extends number,
  C extends any[] = [],
  D extends any[] = [],
  T extends number = Absolute<N>
> = T extends 100 ? 10000 : C["length"] extends T
  ? D["length"]
  : Square<N, [...C, 0], [...D, ...PadList<T>]>;

Solution by vangie #32206

type GetArray<T extends number, U extends any[] = []> = U["length"] extends T
  ? U
  : GetArray<T, [...U, 0]>;

type HandleNumber<T extends number> = `${T}` extends `-${infer N extends number}` ? N : T;

type Square<
  T extends number,
  N extends number = HandleNumber<T>,
  U extends number[] = GetArray<N>,
  A extends number[] = U,
  Count extends number[] = [0]
> = T extends 0
  ? 0
  : Count["length"] extends N
  ? U["length"]
  : Square<T, N, [...U, ...A], A, [...Count, 0]>;

type R = Square<99>;

ζ— ζ³•ι€šθΏ‡100及δ»₯δΈŠηš„η”¨δΎ‹

Solution by moonpoet #31044

type TupleBase = {
  "-": [],
  "0": [],
  "1": [unknown],
  "2": [unknown, unknown],
  "3": [unknown, unknown, unknown],
  "4": [unknown, unknown, unknown, unknown],
  "5": [unknown, unknown, unknown, unknown, unknown],
  "6": [unknown, unknown, unknown, unknown, unknown, unknown],
  "7": [unknown, unknown, unknown, unknown, unknown, unknown, unknown],
  "8": [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown],
  "9": [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]
}

type NumStrToTuple<T extends string, A extends unknown[] = []> =
  T extends `${infer F}${infer R}`
    ? F extends keyof TupleBase
      ? [...A, ...NumStrToTuple<R, [...A, ...A, ...A, ...A, ...A, ...A, ...A, ...A, ...A, ...TupleBase[F]]>]
      : never
    : A

type SquareNumber<
  N extends number,
  I extends unknown[] = [],
  R extends unknown[] = [],
  NUM extends number = NumStrToTuple<`${N}`>['length']
> = NUM extends I['length']
    ? R['length']
    : SquareNumber<N, [...I, unknown], [...R, ...NumStrToTuple<`${N}`>], NUM>

type SquareNumberAndZero<N extends number, Z extends string = ''> =
  `${N}` extends `${infer N extends number}0`
    ? SquareNumberAndZero<N, `00${Z}`>
    : [SquareNumber<N>, Z];

type Square<N extends number> =
  SquareNumberAndZero<N> extends [infer N extends number, infer Z extends string]
    ? `${N}${Z}` extends `${infer R extends number}` ? R : never
    : never

Solution by milletlovemouse #30987

This should work for all the test values without running into any problems.

type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type Tuple<Length extends Digit, Result extends unknown[] = []> = Result["length"] extends Length
    ? Result
    : Tuple<Length, [...Result, unknown]>;
type Carry<N> = N extends number
    ? `${N}` extends `${infer X extends Digit}${infer Y extends Digit}`
        ? [X, Y]
        : `${N}` extends `${infer X extends Digit}`
            ? [0, X]
            : never
    : never;
type AddDigits<N extends Digit, M extends Digit, C extends Digit = 0> = Carry<[...Tuple<N>, ...Tuple<M>, ...Tuple<C>]["length"]>;
type SplitNumber<N extends number | string> = `${N}` extends `${infer X extends Digit}${infer Y}`
    ? [X, ...SplitNumber<Y>]
    : `${N}` extends `${infer X extends Digit}`
        ? [X]
        : [];
type ParseInt<N extends string> = N extends `${infer X extends number}` ? X : never;
type JoinNumberHelper<N> = N extends [infer X extends Digit, ...infer XS extends Digit[]]
    ? `${X}${JoinNumberHelper<XS>}`
    : "";
type JoinNumber<N extends Digit[]> = ParseInt<JoinNumberHelper<N>>;
type PadList<L extends unknown[], N extends number, P = 0, I extends unknown[] = []> = I["length"] extends N
    ? L
    : L[I["length"]] extends undefined
        ? PadList<[P, ...L], N, P, [unknown, ...I]>
        : PadList<L, N, P, [unknown, ...I]>;
type DePadList<L extends unknown[], P = 0> = L extends [P, ...infer XS]
    ? DePadList<XS, P>
    : L;
type AddListsHelper<
    A extends number[],
    B extends number[],
    C extends Digit = 0,
    L = PadList<A, B["length"]>,
    R = PadList<B, A["length"]>
> = L extends [...infer XS extends number[], infer X extends Digit]
    ? R extends [...infer YS extends number[], infer Y extends Digit]
        ? AddDigits<X, Y, C> extends [infer ThisCarry extends Digit, infer ThisDigit extends Digit]
            ? [...AddListsHelper<XS, YS, ThisCarry>, ThisDigit]
            : []
        : []
    : [];
type AddLists<A extends number[], B extends number[]> = DePadList<AddListsHelper<[0, ...A], [0, ...B]>>;
type AddListXTimes<A extends number[], X extends number, O extends number[] = A, I extends unknown[] = [unknown]> = X extends 0
    ? [0]
    : I["length"] extends X
        ? A
        : AddListXTimes<AddLists<A, O>, X, O, [...I, unknown]>;
type Multiply<N extends number, M extends number> = JoinNumber<AddListXTimes<SplitNumber<N>, M>>;
type Abs<N extends number> = `${N}` extends `-${infer X extends number}` ? X : N;
type Square<N extends number, M extends number = Abs<N>> = Multiply<M, M>;

Solution by oathompsonjones #30300

type Reverse<A extends string | number | bigint, _Result extends string = ''> =
  `${ A }` extends `${ infer AH }${ infer AT }`
    ? Reverse<AT, `${ AH }${ _Result }`>
    : _Result

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

type AddOne<A extends string | number> = `${ A }` extends `${ infer AH }${ infer AT }`
  ? AH extends '9'
    ? `0${ AddOne<AT> }`
    : `${ DigsNext[AH & keyof DigsNext] }${ AT }`
  : '1'

type Sum<A extends number | string, B extends number, _Counter extends 0[] = []> =
  _Counter['length'] extends B
    ? A
    : Sum<AddOne<A>, B, [ ..._Counter, 0]>

type TinySum<A extends number | string, B extends number> = Reverse<Sum<Reverse<A>, B>>

type RemoveMinus<N extends number> = `${ N }` extends `-${ infer I extends number }` ? I : N

type Square<
  N extends number,
  _PN extends number = RemoveMinus<N>,
  _N extends number = RemoveMinus<N>,
  _Counter extends 0[] = [0, 0],
  SumN extends number = `${ TinySum<_PN, _N> }` extends `${ infer I extends number }` ? I : never,
> = _PN extends 0 | 1
  ? _PN
  : _Counter['length'] extends _N
    ? SumN
    : Square<0, SumN, _N, [ ..._Counter, 0 ]>

Solution by lvjiaxuan #28354

/*
  27133 - Square
  -------
  by null (@aswinsvijay) #medium #tuple #array #math

  ### Question

  Given a number, your type should return its square.

  > View on GitHub: https://tsch.js.org/27133
*/

/* _____________ Your Code Here _____________ */


/**
 * Grid method multiplication:
 * Involves breaking the numbers down into their individual digits, multiplying each pair of digits separately, and then adding the results.
 *
 * 🍎 (diagonal a) 🫐( (diagonal b) πŸ’ (diagonal c) d: πŸ‡ (diagonal d)
 *
 *       8 (Horizontal)      9 (Horizontal)
 *    -----------------------------------------
 *    |                   |                   |
 *    |     6🍎    4🍎    |     7πŸ’    2πŸ’    | 8 (Vertical)
 *    |                   |                   |
 *    -----------------------------------------
 *    |                   |                   |
 *    |     7🫐    2🫐    |     8πŸ‡    1πŸ‡    |
 *    |                   |                   |
 *    -----------------------------------------
 * 
 * Result is 6400🍎 + 720 πŸ’ + 720🫐 + 81πŸ‡ = 7921
 */

/* 
  This type computes the absolute value of the input number, 
  transforming negative numbers into their positive counterparts.
*/
type Abs<N extends number | string | bigint> = `${N}` extends `-${infer Num extends number}` ? `${Num}` : `${N}`;

/* 
  LastDigit: Extracts the last digit from a numeric string. 
*/
type LastDigit<S extends string> = S extends `${infer Rest}${0|1|2|3|4|5|6|7|8|9}` ? S extends `${Rest}${infer Digit}` ? Digit : never : never;

/* 
  RestDigits: Retrieves all digits except the last from a numeric string.
*/
type RestDigits<S extends string> = S extends `${infer Rest}${0|1|2|3|4|5|6|7|8|9}` ? Rest : never;

/*
  This type multiplying each string-number in an array by 10.
*/
type MultiplyByTen<S extends string[]> = {[Index in keyof S]: S[Index] extends '0' ? '0' : `${S[Index]}0`};

/* 
  This type calculates the product of two digits and multiplies the total products so far by ten.
  The multiplication is represented as appending zeros to the total strings.
  This type utilizes the MultiplicationMap to find the product of the digits.
  The result is an array where each string is a digit product with its appropriate tens-place offset.
*/
type ComputeProductWithOffset<LeftDigit extends string, UpDigit extends string, LeftTotal extends string[], UpTotal extends string[] = []> =
  MultiplicationMap[`${LeftDigit}x${UpDigit}` & keyof MultiplicationMap] extends infer Product extends string
    ? [...MultiplyByTen<UpTotal>, ...MultiplyByTen<LeftTotal>, Product]
    : [...MultiplyByTen<UpTotal>, ...MultiplyByTen<LeftTotal>];

/* 
  This type, ComputeProductsAcrossRow, executes the multiplication for each digit pair along the row (left direction). 
  It does so by recursively shifting to the left until it exhausts all digits in the row.
  It utilizes ComputeProductWithOffset to calculate the product of digits and carry over.
  The resulting array is a collection of string products, each appended with zeros to represent its tens-place offset.
*/
type ComputeProductsAcrossRow<Left extends string, UpDigit extends string> =
  '' extends Left
    ? []
    : ComputeProductWithOffset<LastDigit<Left>, UpDigit, ComputeProductsAcrossRow<RestDigits<Left>, UpDigit>>;

/* 
  This type executes the multiplication process for each digit pair and then moves to the next row (up direction).
  It continues this operation until it traverses all the rows and columns of the number's digits.
*/
type ComputeProductsLeftward<Left extends string, Up extends string> =
  '' extends Left | Up
    ? []
    : ComputeProductWithOffset<LastDigit<Left>, LastDigit<Up>,
        ComputeProductsLeftward<Left, RestDigits<Up>>,
        ComputeProductsAcrossRow<RestDigits<Left>, LastDigit<Up>>>;

/* 
  This type adds two numbers represented as strings.
  It recursively adds each digit from the least significant digit, and carries over as needed.
  Returns the sum as a string.
*/
type Sum<Num1 extends string, Num2 extends string> =
  Num1 extends '' | '0'
    ? Num2
    : Num2 extends '' | '0'
    ? Num1
    : AdditionMap[`${LastDigit<Num1>}+${LastDigit<Num2>}` & keyof AdditionMap] extends `${infer Carry}${infer Digit}`
      ? Sum<RestDigits<Num1>, RestDigits<Num2>> extends infer SumOfRest extends string
        ? `${Sum<SumOfRest, Carry>}${Digit}`
        : never
      : never;

/* 
  This type, SumAllProducts, sums all elements in the input array of strings, which represent digit products offset by tens places. 
  The summation takes place from right to left, emulating the carry-over process in manual addition.
  The result is a string representing the cumulative total.
*/
type SumAllProducts<ProductsWithOffset extends string[]> =
  ProductsWithOffset extends [infer FirstProduct extends string, ...infer RestProduct extends string[]]
    ? Sum<FirstProduct, SumAllProducts<RestProduct>>
    : '0';

/* 
  Square is a type that calculates the square of a number.
  The result is then computed by concatenating the length of each diagonal.
*/
type Square<N extends number> =
  SumAllProducts<ComputeProductsLeftward<Abs<N>, Abs<N>>> extends infer Sum
    ? Sum extends `0${infer Num extends number}`
      ? Num
      : Sum extends `${infer Num extends number}`
        ? Num
        : 0
    : never;

/* 
  AdditionMap is an object that maps an addition operation of two single-digit numbers to its result.
  The result is in string format to facilitate later string concatenation and maintain leading zeroes,
  which are crucial in the grid computation method we're implementing for squaring. 
*/
type AdditionMap = {
  '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',
};

/* 
   MultiplicationMap is an object that maps a multiplication operation of two single-digit numbers to its result.
   Similar to AdditionMap, the result is in string format. This allows for easy string operations later and helps keep leading zeroes,
   which play a significant role in the positioning of the product results in our grid computation.
*/
type MultiplicationMap = {
  '0x0': '00', '0x1': '00', '0x2': '00', '0x3': '00', '0x4': '00', '0x5': '00', '0x6': '00', '0x7': '00', '0x8': '00', '0x9': '00',
  '1x0': '00', '1x1': '01', '1x2': '02', '1x3': '03', '1x4': '04', '1x5': '05', '1x6': '06', '1x7': '07', '1x8': '08', '1x9': '09',
  '2x0': '00', '2x1': '02', '2x2': '04', '2x3': '06', '2x4': '08', '2x5': '10', '2x6': '12', '2x7': '14', '2x8': '16', '2x9': '18',
  '3x0': '00', '3x1': '03', '3x2': '06', '3x3': '09', '3x4': '12', '3x5': '15', '3x6': '18', '3x7': '21', '3x8': '24', '3x9': '27',
  '4x0': '00', '4x1': '04', '4x2': '08', '4x3': '12', '4x4': '16', '4x5': '20', '4x6': '24', '4x7': '28', '4x8': '32', '4x9': '36',
  '5x0': '00', '5x1': '05', '5x2': '10', '5x3': '15', '5x4': '20', '5x5': '25', '5x6': '30', '5x7': '35', '5x8': '40', '5x9': '45',
  '6x0': '00', '6x1': '06', '6x2': '12', '6x3': '18', '6x4': '24', '6x5': '30', '6x6': '36', '6x7': '42', '6x8': '48', '6x9': '54',
  '7x0': '00', '7x1': '07', '7x2': '14', '7x3': '21', '7x4': '28', '7x5': '35', '7x6': '42', '7x7': '49', '7x8': '56', '7x9': '63',
  '8x0': '00', '8x1': '08', '8x2': '16', '8x3': '24', '8x4': '32', '8x5': '40', '8x6': '48', '8x7': '56', '8x8': '64', '8x9': '72',
  '9x0': '00', '9x1': '09', '9x2': '18', '9x3': '27', '9x4': '36', '9x5': '45', '9x6': '54', '9x7': '63', '9x8': '72', '9x9': '81',
};

/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Square<0>, 0>>,
  Expect<Equal<Square<1>, 1>>,
  Expect<Equal<Square<3>, 9>>,
  Expect<Equal<Square<20>, 400>>,
  Expect<Equal<Square<100>, 10000>>,

  // Negative numbers
  Expect<Equal<Square<-2>, 4>>,
  Expect<Equal<Square<-5>, 25>>,
  Expect<Equal<Square<-31>, 961>>,
  Expect<Equal<Square<-50>, 2500>>,
  
  // Abs
  Expect<Equal<Abs<0>, '0'>>,
  Expect<Equal<Abs<1>, '1'>>,
  Expect<Equal<Abs<-1>, '1'>>,
  Expect<Equal<Abs<9999999999>, '9999999999'>>,
  Expect<Equal<Abs<-9999999999>, '9999999999'>>,

  // LastDigit
  Expect<Equal<LastDigit<'0'>, '0'>>,
  Expect<Equal<LastDigit<'100'>, '0'>>,
  Expect<Equal<LastDigit<'1'>, '1'>>,
  Expect<Equal<LastDigit<'109'>, '9'>>,

  // RestDigits
  Expect<Equal<RestDigits<'0'>, ''>>,
  Expect<Equal<RestDigits<'100'>, '10'>>,
  Expect<Equal<RestDigits<'1'>, ''>>,
  Expect<Equal<RestDigits<'109'>, '10'>>,

  // MultiplyByTen
  Expect<Equal<MultiplyByTen<['0', '1', '10', '100']>, ['0', '10', '100', '1000']>>,

  // Sum
  Expect<Equal<Sum<'0', '0'>, '0'>>,
  Expect<Equal<Sum<'0', '1'>, '1'>>,
  Expect<Equal<Sum<'1', '0'>, '1'>>,
  Expect<Equal<Sum<'1', '10'>, '11'>>,

  Expect<Equal<ComputeProductsAcrossRow<'12', '1'>, ['010', '02']>>,

  // ComputeProductsLeftward
  Expect<Equal<ComputeProductsLeftward<'98', '98'>, ["720", "8100", "720", "64"]>>,

  // SumAllProducts
  Expect<Equal<SumAllProducts<['1', '10']>, '11'>>,
]

/* _____________ Further Steps _____________ */
/*
  > Share your solutions: https://tsch.js.org/27133/answer
  > View solutions: https://tsch.js.org/27133/solutions
  > More Challenges: https://tsch.js.org
*/

Playground

Solution by teamchong #27822

type MakeArr<N extends number, Acc extends any[] = []> = Acc["length"] extends N
  ? Acc
  : MakeArr<N, [...Acc, any]>;

type Abs<N extends number> = `${N}` extends `-${infer R extends number}`
  ? R
  : N;

type Trim0<
  N extends number,
  Acc extends number = 0
> = `${N}` extends `${infer R extends number}0`
  ? [...MakeArr<Acc>, any] extends any[]
    ? Trim0<R, [...MakeArr<Acc>, any]["length"]>
    : never
  : [N, Acc]; // N is the number without trailing 0s and Acc is the number of trailing 0s

// Get "000.." string whose length is S
type MakeDouble0Str<
  S extends number,
  Acc extends string = "",
  T extends any[] = [...MakeArr<S>, ...MakeArr<S>]
> = T extends [any, ...infer T]
  ? MakeDouble0Str<T["length"], `${Acc}0`, T>
  : Acc;

type CalcSquare<
  N extends number,
  S extends number = N,
  Acc extends any[] = []
> = S extends 0
  ? Acc["length"]
  : MakeArr<S> extends [any, ...infer R]
  ? CalcSquare<N, R["length"], [...Acc, ...MakeArr<N>]>
  : never;

type Square<
  N extends number,
  T extends number = Trim0<Abs<N>>["0"],
  S extends number = Trim0<Abs<N>>["1"]
> = S extends 0
  ? CalcSquare<T>
  : `${CalcSquare<T>}${MakeDouble0Str<S>}` extends `${infer S extends number}`
  ? S
  : never;

Solution by HiroNonoyama #27631

type Range<N extends number, C extends any[] = []> = C["length"] extends N
  ? C
  : Range<N, [any, ...C]>

type SquareRange<
  N extends number,
  C extends any[] = [],
  R extends any[] = []
> = C["length"] extends N
  ? R["length"]
  : SquareRange<N, [any, ...C], [...Range<N>, ...R]>

type Abs<T extends number> = `${T}` extends `-${infer N extends number}` ? N : T

type TrimZero<T extends number> = `${T}` extends `${infer N extends number}0`
  ? TrimZero<N>
  : T

type DupZero<
  T extends number,
  R extends string = ""
> = `${T}` extends `${infer N extends number}0` ? DupZero<N, `${R}00`> : R

type AsNumber<T> = T extends infer X extends number ? X : never

type ToNumber<T> = T extends `${infer X extends number}` ? X : never

type Square<N extends number> = ToNumber<`${AsNumber<SquareRange<TrimZero<Abs<N>>>>}${DupZero<N>}`>

This impl can't solve numbers like Square<101>. N has to be (-99 ~ 99) * 10^n

Solution by shuji-koike #27516

type MakeCounter<T extends number, _Result extends 1[] = []> = _Result[`length`] extends T | 999 ? _Result : MakeCounter<T, [..._Result, 1]>;
/**ζ‰εΉ³εŒ– */
type FlatCounterCounter<T extends any[][], _Result extends any[] = []> = T extends [infer F extends any[], ...infer R extends any[][]] ?
  FlatCounterCounter<R, [..._Result, ...F]> :
  _Result;
type SimpleMultiply<T extends number, U extends number, _CounterCounter extends 1[][] = []> = T | U extends 100 ? 10000 : _CounterCounter[`length`] extends U ?
  FlatCounterCounter<_CounterCounter>[`length`] :
  SimpleMultiply<T, U, [..._CounterCounter, MakeCounter<T>]>;

/**100δ»₯ε†… */
type Square<N extends number> = `${N}` extends `-${infer NN extends number}` ? SimpleMultiply<NN, NN> : SimpleMultiply<N, N>;

//---------------------------------- large number version ----------------------------------
// namespace multiply {
//   /**0~9 */
//   type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
//   /**δΈͺ位 RRRF ==> F */
//   type DigitFirst<T extends string | number | bigint> = T extends string ?
//     (Number<T> extends Digit ?
//       Number<T> :
//       (T extends `${number}${infer R}` ? DigitFirst<R> : never)) :
//     DigitFirst<`${T}`>;
//   /**δΈͺ位δ»₯上 RRRF ==> RRR */
//   type DigitRest<T extends string | number | bigint, _Result extends string = ``> = T extends string ?
//     (T extends `${infer F}${infer R extends `${any}${any}`}` ?
//       DigitRest<R, `${_Result}${F}`> :
//       Number<_Result> extends 0/*去0*/ ? `` : _Result) :
//     DigitRest<`${T}`>;
//   type MakeCounter<T extends number, _Result extends 1[] = []> = _Result[`length`] extends T ? _Result : MakeCounter<T, [..._Result, 1]>;
//   /**δΈͺδ½η›ΈεŠ  */
//   type DigitAdd<X extends Digit, Y extends Digit> = [...MakeCounter<X>, ...MakeCounter<Y>][`length`] extends (infer N extends number) ? N : 0;
//   /**Parse Int */
//   type Number<T extends string | number | bigint> = T extends `0${infer R}`/*去0*/ ? Number<R> : T extends `${infer N extends number | bigint}` ? N : 0;
//   /**+1οΌˆθΏ›δ½οΌ‰ */
//   type AddOne<T extends number | string, _DigitAdd extends number = DigitAdd<DigitFirst<T>, 1>> = `${_DigitAdd extends Digit ? DigitRest<T> : /*进位*/AddOne<DigitRest<T>>}${DigitFirst<_DigitAdd>}`;
//   /**δΈͺ位乘 */
//   type DigitMultiply<T extends string | number | bigint, U extends Digit, _Counter extends 1[] = [], _Result extends string = `0`> = _Counter[`length`] extends U ? _Result : DigitMultiply<T, U, [..._Counter, 1], Sum<_Result, T>>;
//   /**x10^n */
//   type TenPow<T extends string | number | bigint, N extends number, _Counter extends 1[] = []> = _Counter[`length`] extends N ? T : `${TenPow<T, N, [..._Counter, 1]>}0`;

//   /**εŠ ζ³•ε™¨οΌˆθ‡ͺη„Άζ•°οΌ‰ */
//   type Sum<A extends string | number | bigint, B extends string | number | bigint, _Result extends string = ``, _DigitAdd extends number = DigitAdd<DigitFirst<A>, DigitFirst<B>>> =
//     `${A}${B}` extends `` ? _Result :    //return
//     Sum<DigitRest<A>, _DigitAdd extends Digit ? DigitRest<B> : /*进位*/AddOne<DigitRest<B>>, `${DigitFirst<_DigitAdd>}${_Result}`>;

//   /**δΉ˜ζ³•ε™¨οΌˆθ‡ͺη„Άζ•°οΌ‰ */
//   export type Multiply<A extends string | number | bigint, B extends string | number | bigint, _CarryCounter extends 1[] = [], _Result extends string = `0`> = B extends `` ? Number<_Result> :    //return
//     Multiply<A, DigitRest<B>, [..._CarryCounter, 1], Sum<_Result, TenPow<DigitMultiply<A, DigitFirst<B>>, _CarryCounter[`length`]>>>;
//   // 123 * 12345 ==>   (123 *     5)
//   //             ==> + (123 *    40)
//   //             ==> + (123 *   300)
//   //             ==> + (123 *  2000)
//   //             ==> + (123 * 10000)
// }

// /**δΉ˜ζ³•ε™¨ε€„η†θΆ…ε€§ζ•° */
// type Square<N extends number> = `${N}` extends `-${infer NN extends number}` ? multiply.Multiply<NN, NN> : multiply.Multiply<N, N>;

// type test_large_number = Square<3141592662951413>
//---------------------------------- large number version ----------------------------------

Solution by E-uler #27396

type TupLen<T extends number, U extends number[] = []> = T extends 0 ? 
  [] : 
    U['length'] extends T ?
      U : 
        TupLen<T, [T, ...U]>;

type Abs<T extends number> = T extends 0 ? 
  T : 
  `${T}` extends `-${infer U extends number}` ? 
    U : 
      T;

type NRange<T extends number, U extends any[] = []> = U['length'] extends T ? U : NRange<T, [...U, 0]>

type Flatten<T, U extends any[] = []> = T extends []
    ? U
    : T extends [infer F, ...infer R]
    ? Flatten<R, [...U, ...Flatten<F>]>
    : [...U, T]

type TupleSum<T extends number[]> = Flatten<{ [K in keyof T]: NRange<T[K]> }>['length']

type Square<T extends number> = Abs<T> extends 100 ? 10000 : TupleSum<TupLen<Abs<T>>>;

My implementation only works with numbers between -100 and 100

Solution by jjswifty #27391