这是indexloc提供的服务,不要输入任何密码
Skip to content

300 - String To Number (🎥 Video Explanation and Solution) #25923

@dimitropoulos

Description

@dimitropoulos

300 - String To Number

As of TypeScript 4.8 this has a super trivial one-line solution, but before that it was quite intense. The solutions on this video are more like an archaeological dig than anything else.

🎥 Video Explanation

Release Date: 2023-04-10 19:00 UTC

String To Number

🔢 Code

// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'

type A1 = ToNumber<'0'>;
type B1 = 0;
type C1 = Expect<Equal<A1, B1>>;

type A2 = ToNumber<'5'>;
type B2 = 5;
type C2 = Expect<Equal<A2, B2>>;

type A3 = ToNumber<'12'>;
type B3 = 12;
type C3 = Expect<Equal<A3, B3>>;

type A4 = ToNumber<'27'>;
type B4 = 27;
type C4 = Expect<Equal<A4, B4>>;

type A5 = ToNumber<'18@7_$%'>;
type B5 = never;
type C5 = Expect<Equal<A5, B5>>;

// // ============= Your Code Here =============
// // /** TypeScript 4.8: https://devblogs.microsoft.com/typescript/announcing-typescript-4-8-beta/#infer-types-template-strings */
// type ToNumber<T> =
//   T extends `${infer N extends number}`
//   ? N
//   : never;

// type ToNumber<
//   T extends string,
//   Count extends '🧮'[] = []
// > =
//   T extends `${number}`
//   ? T extends `${Count["length"]}`
//     ? Count["length"]
//     : ToNumber<T, [...Count, '🧮']>
//   : never;

// // ================== NOPE ==================
// // Type instantiation is excessively deep
// //   and possibly infinite.ts(2589)
// type ToNumber<
//   T extends string,
//   Count extends 1[] = []
// > =
//   T extends `${Count["length"]}`
//   ? Count["length"]
//   : ToNumber<T, [...Count, 1]>;


// ============== Alternative ==============
// @uid11
type Num = readonly 0[]

/**
 * NumToNumber<Num3> = 3, where Num3 = [0, 0, 0]
 */
type NumToNumber<N extends Num> = N['length']

type Digit =
  | '0' | '1' | '2' | '3' | '4'
  | '5' | '6' | '7' | '8' | '9'

/**
 * MultiplyToDigit<'3', Num2> = Num6
 */
type MultiplyToDigit<D extends Digit, N extends Num> = {
  '0': [],
  '1': N,
  '2': [...N, ...N],
  '3': [...N, ...N, ...N],
  '4': [...N, ...N, ...N, ...N],
  '5': [...N, ...N, ...N, ...N, ...N],
  '6': [...N, ...N, ...N, ...N, ...N, ...N],
  '7': [...N, ...N, ...N, ...N, ...N, ...N, ...N],
  '8': [...N, ...N, ...N, ...N, ...N, ...N, ...N, ...N],
  '9': [...N, ...N, ...N, ...N, ...N, ...N, ...N, ...N, ...N],
}[D]

/**
 * Num1
 */
type One = [0]

/**
 * DigitToNum<'2'> = Num2
 */
type DigitToNum<D extends Digit> = MultiplyToDigit<D, One>

/**
 * Sum<Num2, Num3> = Num5
 */
type Sum<N extends Num, M extends Num> = [...N, ...M]

/**
 * MultiplyTo10<Num2> = Num20
 */
type MultiplyTo10<N extends Num> =
  MultiplyToDigit<
    '2',
    MultiplyToDigit<'5', N>
  >

/**
 * GetBase<'2'> = Num10, GetBase<'31'> = Num100
 */
type GetBase<Number extends string> =
  Number extends Digit
  ? MultiplyTo10<One>
  : Number extends `${string}${infer Rest}`
    ? MultiplyTo10<GetBase<Rest>>
    : never

/**
 * StrToNum<'13'> = Num13
 */
type StrToNum<Str extends string> = Str extends Digit
  ? MultiplyToDigit<Str, One>
  : Str extends `${infer D}${infer Rest}`
    ? D extends Digit
      ? Sum<
          MultiplyToDigit<D, GetBase<Rest>>,
          StrToNum<Rest>
        >
      : never
    : never

/**
 * ToNumber<'24'> = 24
 */
type ToNumber<S extends string> = NumToNumber<StrToNum<S>>

➕ More Solutions

For more video solutions to other challenges: see the umbrella list! #21338

Metadata

Metadata

Assignees

No one assigned

    Labels

    300answerShare answers/solutions to a questionenin English

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions