type ToInt<S> = S extends `0${infer X}` ? ToInt<X> : S extends `${infer N extends number}` ? N : 0;
type Q1 = string;
type Q10 = `${Q1}${Q1}${Q1}${Q1}${Q1}${Q1}${Q1}${Q1}${Q1}${Q1 & {}}`;
type Q100 = `${Q10}${Q10}${Q10}${Q10}${Q10}${Q10}${Q10}${Q10}${Q10}${Q10}`;
type Q1000 = `${Q100}${Q100}${Q100}${Q100}${Q100}${Q100}${Q100}${Q100}${Q100}${Q100}`;
type Q10k = `${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}${Q1000}`;
type Q100k = `${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}${Q10k}`;
type Len<S, Q extends string, R extends 1[] = []> = S extends `${Q}${infer T}`
? Len<T, Q, [...R, 1]>
: [R['length'], S];
type LengthOfString<S extends string> = Len<S, Q100k> extends [infer A extends number, infer S1]
? Len<S1, Q10k> extends [infer B extends number, infer S2]
? Len<S2, Q1000> extends [infer C extends number, infer S3]
? Len<S3, Q100> extends [infer D extends number, infer S4]
? Len<S4, Q10> extends [infer E extends number, infer S5]
? Len<S5, Q1> extends [infer F extends number, string]
? ToInt<`${A}${B}${C}${D}${E}${F}`>
: 0
: 0
: 0
: 0
: 0
: 0;
Solution by alexandroppolus #33269
I prefer not to hardcode a specific length for the assessment, as the logic should theoretically handle strings of any length. However, in practice, excessively long strings can cause browser issues. Despite this limitation, I aim for the logic to support strings of any length.
While many prefer concise solutions, my focus is on addressing edge cases and optimizing performance to ensure robustness and scalability, even if it requires a more detailed implementation.
// Performance Note:
// The nested structure of these types is designed for efficiency. By reducing the size of S incrementally and
// processing it in chunks (one `L` at a time), we minimize the amount of data being processed in each recursive step.
// This improves performance and avoids working with excessively long strings, which could slow down type evaluation.
// Entry point: Calculate the length of string S by recursively breaking it into parts
type LengthOfString<S extends string, L extends string = `${any}`, R extends string = ''>
= S extends `${L}${infer _1}` ? RemainderLength<_1, L, R> : DigitAccumulator<S, R, '0'>
// Recursive helper: Used after the initial 10 levels of recursion, processes the remaining length of S
type RemainderLength<_1 extends string, L extends string, R extends string>
= _1 extends `${L}${infer _2}`
? _2 extends `${L}${infer _3}`
? _3 extends `${L}${infer _4}`
? _4 extends `${L}${infer _5}`
? _5 extends `${L}${infer _6}`
? _6 extends `${L}${infer _7}`
? _7 extends `${L}${infer _8}`
? _8 extends `${L}${infer _9}`
? _9 extends `${L}${infer _10}`
// Continue breaking down the string into chunks of L until all parts are processed
? RemainderLength<_10, `${L}${L}${L}${L}${L}${L}${L}${L}${L}${L}`, `${L}.${R}`>
: DigitAccumulator<_9, R, '9'>
: DigitAccumulator<_8, R, '8'>
: DigitAccumulator<_7, R, '7'>
: DigitAccumulator<_6, R, '6'>
: DigitAccumulator<_5, R, '5'>
: DigitAccumulator<_4, R, '4'>
: DigitAccumulator<_3, R, '3'>
: DigitAccumulator<_2, R, '2'>
: DigitAccumulator<_1, R, '1'>
// Final helper: Accumulates the count of digits for the remaining parts of S
type DigitAccumulator<S extends string, R extends string, A extends string = ''>
= R extends `${infer L}.${infer R}`
? S extends `${L}${infer _1}`
? _1 extends `${L}${infer _2}`
? _2 extends `${L}${infer _3}`
? _3 extends `${L}${infer _4}`
? _4 extends `${L}${infer _5}`
? _5 extends `${L}${infer _6}`
? _6 extends `${L}${infer _7}`
? _7 extends `${L}${infer _8}`
? _8 extends `${L}${infer _9}`
// Reduce string S by one `L` at a time to minimize its size and improve performance
? DigitAccumulator<_9, R, `${A}9`>
: DigitAccumulator<_8, R, `${A}8`>
: DigitAccumulator<_7, R, `${A}7`>
: DigitAccumulator<_6, R, `${A}6`>
: DigitAccumulator<_5, R, `${A}5`>
: DigitAccumulator<_4, R, `${A}4`>
: DigitAccumulator<_3, R, `${A}3`>
: DigitAccumulator<_2, R, `${A}2`>
: DigitAccumulator<_1, R, `${A}1`>
: DigitAccumulator<S, R, `${A}0`>
: A extends `${infer N extends number}` ? N : never
Solution by teamchong #33139