00651-hard-length-of-string-2

Back

// 你的答案
type LengthOfString<S extends string, Strs extends any[] = []> = S extends `${infer A}${infer Rest}`
                                                                ? A extends ''
                                                                  ? 0
                                                                  : LengthOfString<Rest, [...Strs, A]>
                                                                : Strs["length"]

Solution by Codec-k #32084

type LengthOfString<
  S extends string,
  L extends string[] = []
> = S extends `${infer S}${infer Tail}`
  ? LengthOfString<Tail, [S, ...L]>
  : L["length"]

Solution by Kying-star #29004

type LengthOfString<S extends string, _Acc extends number[] = []> =
  S extends `${string}${infer Rest}` ? LengthOfString<Rest, [..._Acc, 0]> : _Acc['length']

Solution by jjswifty #28926

type LengthOfString<S extends string, R extends any[] = []> = S extends ${infer F}${infer L} ? LengthOfString<L, [...R,F]> : R['length']

Solution by Xjc666666 #28909

Not sure if I missed something, but this one is a lot shorter (and has a better readability I think) than solutions with infer A0, ..., infer A9, infer Rest. Please correct me if I overlooked something.

type LengthOfString<
  S extends string,
  C extends number[] = [],
> = S extends `${infer _}${infer Rest}`
  ? LengthOfString<Rest, [...C, 0]>
  : C['length']

Solution by furkandmrblk #27813

type GetHaveString<A, B> = A extends "" ? B : A;
type Build<
  T extends number,
  Result extends Array<never> = []
> = Result["length"] extends T ? Result : Build<T, [...Result, never]>;

type Add<A extends number, B extends number> = [
  ...Build<A>,
  ...Build<B>
]["length"];
type stringToNumber<T> = `${T & string}` extends `${infer A extends number}`
  ? A
  : never;
type Add2<A extends number, B extends number> = `${Add<A, B> &
  number}` extends `1${infer G extends number}`
  ? {
      overflow: 1;
      value: G;
    }
  : {
      overflow: 0;
      value: Add<A, B>;
    };
type Reverse<T extends string | number | bigint> =
  `${T}` extends `${infer A}${infer B}` ? `${Reverse<B>}${A}` : T;

type GetSLast1<T extends string | number | bigint> =
  `${T}` extends `${infer A}${infer B}` ? stringToNumber<A> : "";

type GetSLast<
  T extends string | number | bigint,
  B extends string | number | bigint
> = [GetSLast1<T>, GetSLast1<B>];
type GetSOther<T extends string | number | bigint> =
  `${T}` extends `${infer A}${infer B}` ? B : "";
type Sum1<
  A extends string | number | bigint,
  B extends string | number | bigint,
  Overflow extends number = 0,
  Result extends string = ""
> = [""] extends [A | B]
  ? [A, B] extends ["", ""]
    ? `${Result}${Overflow extends 0 ? "" : Overflow}`
    : GetHaveString<A, B> extends `${infer Z}`
    ? Z extends ""
      ? Result
      : Sum1<Z, Overflow, 0, Result>
    : never
  : GetSLast<A, B> extends [infer A1 extends number, infer B1 extends number]
  ? Add2<Add<A1, Overflow> & number, B1> extends {
      overflow: infer O extends number;
      value: infer V;
    }
    ? Sum1<GetSOther<A>, GetSOther<B>, O, `${Result}${V & number}`>
    : never
  : Result;

type Sum<
  A extends string | number | bigint,
  B extends string | number | bigint
> = Reverse<Sum1<Reverse<A>, Reverse<B>>>;
type parseNum<T> = T extends `${infer C extends number}` ? C : never;

type LengthOfString<
  S extends string,
  V extends number = 0
> = S extends `${infer A}${infer B}`
  ? LengthOfString<B, parseNum<Sum<V, 1>>>
  : V;

Solution by so11y #27220

type LengthOfString<S extends string, L extends string[] = []> = S extends `${infer First}${infer Rest}` ? LengthOfString<Rest, [...L, First]> : L['length']

Solution by JhonLandy #25779

651 - Length of String 2

We've sortof solved this challenge before.. like.. exactly. You may then be wondering why we're doing it again and why this time it's listed as "hard". Well I guess you'll have to watch and find out.

🎥 Video Explanation

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

Length of String 2

🔢 Code

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

type cases = [
  IsTrue<Equal<LengthOfString<''>, 0>>,
  IsTrue<Equal<LengthOfString<'1'>, 1>>,
  IsTrue<Equal<LengthOfString<'12'>, 2>>,
  IsTrue<Equal<LengthOfString<'123'>, 3>>,
  IsTrue<Equal<LengthOfString<'1234'>, 4>>,
  IsTrue<Equal<LengthOfString<'12345'>, 5>>,
  IsTrue<Equal<LengthOfString<'123456'>, 6>>,
  IsTrue<Equal<LengthOfString<'1234567'>, 7>>,
  IsTrue<Equal<LengthOfString<'12345678'>, 8>>,
  IsTrue<Equal<LengthOfString<'123456789'>, 9>>,
  IsTrue<Equal<LengthOfString<'1234567890'>, 10>>,
  IsTrue<Equal<LengthOfString<'12345678901'>, 11>>,
  IsTrue<Equal<LengthOfString<'123456789012'>, 12>>,
  IsTrue<Equal<LengthOfString<'1234567890123'>, 13>>,
  IsTrue<Equal<LengthOfString<'12345678901234'>, 14>>,
  IsTrue<Equal<LengthOfString<'123456789012345'>, 15>>,
  IsTrue<Equal<LengthOfString<'1234567890123456'>, 16>>,
  IsTrue<Equal<LengthOfString<'12345678901234567'>, 17>>,
  IsTrue<Equal<LengthOfString<'123456789012345678'>, 18>>,
  IsTrue<Equal<LengthOfString<'1234567890123456789'>, 19>>,
  IsTrue<Equal<LengthOfString<'12345678901234567890'>, 20>>,
  IsTrue<Equal<LengthOfString<'123456789012345678901'>, 21>>,
  IsTrue<Equal<LengthOfString<'1234567890123456789012'>, 22>>,
  IsTrue<Equal<LengthOfString<'12345678901234567890123'>, 23>>,
  IsTrue<Equal<LengthOfString<'aaaaaaaaaaaaggggggggggggggggggggkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>, 272>>,
  IsTrue<Equal<LengthOfString<'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'>, 999>>,
];

// ============= Your Code Here =============
type LengthOfString<
  T extends string,
  Acc extends string[] = []
> =
  T extends `${string}${infer T}`
  ? LengthOfString<T, [string, ...Acc]>
  : Acc["length"];

type s = string;
type LengthOfString<
  T extends string,
  Acc extends 1[] = []
> =
  T extends `${s}${s}${s}${s}${s}${s}${s}${s}${s}${s}${
    infer Rest
  }`
  ? LengthOfString<Rest, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...Acc]>
  : T extends `${s}${infer Rest}`
    ? LengthOfString<Rest, [1, ...Acc]>
    : Acc["length"];

// ================== NOPE ==================
type StringToTuple<T extends string> =
  T extends `${T[0]}${infer Rest}`
  ? [T, ...StringToTuple<Rest>]
  : [];

type LengthOfString<T extends string> =
  StringToTuple<T>['length'];

➕ More Solutions

For more video solutions to other challenges: see the umbrella list! https://github.com/type-challenges/type-challenges/issues/21338

Solution by dimitropoulos #25349

type LengthOfString<S extends string, _Counter extends string[] = []> = S extends `${infer F}${infer R}` ? LengthOfString<R, [..._Counter, F]> : _Counter[`length`];

Solution by E-uler #24886

type LengthOfString<S extends string, Acc extends string[] = []> = S extends `${infer First}${infer Rest}`
? LengthOfString<Rest, [...Acc, First]>
: Acc['length']

Solution by NeylonR #24448

// your answers
type LengthOfString<S extends string, A extends string[] = []> = S extends `${infer F}${infer Rest}` ? LengthOfString<Rest, [...A, F]> : A['length']

Solution by jxhhdx #24290

// your answers
type LengthOfString<S extends string, Acc extends unknown[] = []> = S extends `${infer F}${infer R}` ? 
LengthOfString<R, [...Acc, F]> : Acc['length']

Solution by snakeUni #23658

Most of other solutions are just a straight recursive approach from the Medium version, I think this challenge requires tweaking.

My solution works up until max tuple length is reached

type Tuple1 = [0];
type Tuple2 = [...Tuple1, ...Tuple1];
type Tuple4 = [...Tuple2, ...Tuple2];
type Tuple8 = [...Tuple4, ...Tuple4];
type Tuple16 = [...Tuple8, ...Tuple8];
type Tuple32 = [...Tuple16, ...Tuple16];
type Tuple64 = [...Tuple32, ...Tuple32];
type Tuple128 = [...Tuple64, ...Tuple64];
type Tuple256 = [...Tuple128, ...Tuple128];
type Tuple512 = [...Tuple256, ...Tuple256];
type Tuple1024 = [...Tuple512, ...Tuple512];

type String1<S extends string> = S extends '' ? never : S;
type String2<S extends string> = S extends `${String1<infer A1>}${String1<infer A2>}${string}` ? `${A1}${A2}` : never;
type String4<S extends string> = S extends `${String2<S>}${infer Rest}` ? `${String2<S>}${String2<Rest>}` : never
type String8<S extends string> = S extends `${String4<S>}${infer Rest}` ? `${String4<S>}${String4<Rest>}` : never
type String16<S extends string> = S extends `${String8<S>}${infer Rest}` ? `${String8<S>}${String8<Rest>}` : never
type String32<S extends string> = S extends `${String16<S>}${infer Rest}` ? `${String16<S>}${String16<Rest>}` : never
type String64<S extends string> = S extends `${String32<S>}${infer Rest}` ? `${String32<S>}${String32<Rest>}` : never
type String128<S extends string> = S extends `${String64<S>}${infer Rest}` ? `${String64<S>}${String64<Rest>}` : never
type String256<S extends string> = S extends `${String128<S>}${infer Rest}` ? `${String128<S>}${String128<Rest>}` : never
type String512<S extends string> = S extends `${String256<S>}${infer Rest}` ? `${String256<S>}${String256<Rest>}` : never
type String1024<S extends string> = S extends `${String512<S>}${infer Rest}` ? `${String512<S>}${String512<Rest>}` : never

type StrLen<S extends string, Calc extends unknown[]> =
  S extends `${String1024<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple1024]> :
  S extends `${String512<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple512]> :
  S extends `${String256<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple256]> :
  S extends `${String128<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple128]> :
  S extends `${String64<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple64]> :
  S extends `${String32<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple32]> :
  S extends `${String16<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple16]> :
  S extends `${String8<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple8]> :
  S extends `${String4<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple4]> :
  S extends `${String2<S>}${infer Rest}` ? StrLen<Rest, [...Calc,...Tuple2]> :
  S extends `${String1<S>}` ? [...Calc,...Tuple1] : Calc;

type LengthOfString<S extends string> = StrLen<S, []>['length'];

Solution by juh9870 #23062

type LengthOfString<S extends string, U extends string[] = []> = 
  S extends `${infer F}${infer R}`
    ? LengthOfString<R, [...U, F]>
    : U["length"] & number

Solution by ivbrajkovic #22255

type LengthOfString<T extends string, Res extends string[] = []> = 
    T extends `${infer A1}${infer A2}${infer A3}${infer A4}${infer A5}${infer A6}${infer A7}${infer A8}${infer A9}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer D1}${infer D2}${infer D3}${infer D4}${infer D5}${infer D6}${infer D7}${infer D8}${infer D9}${infer E1}${infer E2}${infer E3}${infer E4}${infer E5}${infer E6}${infer E7}${infer E8}${infer E9}${infer F1}${infer F2}${infer F3}${infer F4}${infer F5}${infer F6}${infer F7}${infer F8}${infer F9}${infer R}` ? LengthOfString<R, [A1, A2, A3, A4, A5, A6, A7, A8, A9, B1, B2, B3, B4, B5, B6,B7, B8, B9, C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2,D3,D4,D5,D6,D7,D8,D9,E1,E2,E3,E4,E5,E6,E7,E8,E9,F1,F2,F3,F4,F5,F6,F7,F8,F9, ...Res]> 
  : T extends `${infer A1}${infer A2}${infer A3}${infer A4}${infer A5}${infer A6}${infer A7}${infer A8}${infer A9}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer C1}${infer C2}${infer C3}${infer C4}${infer C5}${infer C6}${infer C7}${infer C8}${infer C9}${infer D1}${infer D2}${infer R}` ? LengthOfString<R, [A1, A2, A3, A4, A5, A6, A7, A8, A9, B1, B2, B3, B4, B5, B6,B7, B8, B9, C1,C2,C3,C4,C5,C6,C7,C8,C9,D1,D2, ...Res]> 
  : T extends `${infer A1}${infer A2}${infer A3}${infer A4}${infer A5}${infer A6}${infer A7}${infer A8}${infer A9}${infer B1}${infer B2}${infer B3}${infer B4}${infer B5}${infer B6}${infer B7}${infer B8}${infer B9}${infer R}` ?  LengthOfString<R, [A1, A2, A3, A4, A5, A6, A7, A8, A9, B1, B2, B3, B4, B5, B6,B7, B8, B9, ...Res]> 
  : T extends `${infer A1}${infer A2}${infer A3}${infer A4}${infer A5}${infer A6}${infer A7}${infer A8}${infer A9}${infer R}` ? LengthOfString<R, [A1, A2, A3, A4, A5, A6, A7, A8, A9, ...Res]> 
  : T extends `${infer A1}${infer A2}${infer A3}${infer A4}${infer A5}${infer R}` ? LengthOfString<R, [A1, A2, A3, A4, A5, ...Res]> 
  : T extends `${infer A1}${infer A2}${infer R}` ? LengthOfString<R, [A1, A2, ...Res]> 
  : T extends `${infer A1}${infer R}` ? LengthOfString<R, [A1, ...Res]> : Res["length"];

Solution by acwink #22108

type LengthOfString<S extends string, C extends unknown[]=[]> = S extends `${string}${infer Rest}` ?
 LengthOfString<Rest, [...C, 0]> : C['length'];

Solution by Karamuto #22017

type String2Tuple<S extends string, T extends unknown[] = []> = 
  S extends `${any}${infer Rest}`
    ? String2Tuple<Rest, [unknown, ...T]>
    : T

type LengthOfString<S extends string> = String2Tuple<S>['length']

Key: String2Tuple should be tail recursive.

Solution by zhaoyao91 #21198

// your answers
type CreateArrByNum<N extends number,Arr extends any[] = []> = Arr['length'] extends N ? Arr : Arr extends [...infer Rest] ? CreateArrByNum<N,[...Rest,1]> : Arr
type IncreaseLen<A extends any[]> = A extends [...infer Rest] ? [...Rest,1]['length'] : []
type LengthOfString<S extends string,C extends number = 0> = S extends `${infer F}${infer R}` ? F extends '' ? GetLen<CreateArrByNum<C>> : LengthOfString<R,IncreaseLen<CreateArrByNum<C>>> : GetLen<CreateArrByNum<C>>

type GetLen<T extends any[]> = T['length']

Solution by YqxLzx #21086

// your answers
type LastIndexOf1<
  T,
  Arr extends unknown[] = []
> = T extends `${infer f}${infer r}`
  ? LastIndexOf1<r, [...Arr, 1]>
  : Arr["length"];

Solution by fengjinlong #20244

type LengthOfString<S extends string, CountArr extends string[] = []> = S extends `${infer TFirst}${infer TRest}` ? LengthOfString<TRest, [...CountArr, TFirst]> : CountArr['length']

Solution by HiiiiD #20173

type LengthOfString<S extends string, T extends any[] = [], Temp extends string = '', TempArr extends any[] = []> = S extends `${infer F}${infer R}`
  ? Temp extends ''
    ? LengthOfString<R, [...T, any], F, [any]>
    : S extends `${infer P extends Temp}${infer Q}`
      ? LengthOfString<Q, [...T, ...TempArr], `${Temp}${Temp}`, [...TempArr, ...TempArr]>
      : LengthOfString<R, [...T, any], F, [any]>
  : T['length'];

Solution by logan70 #19378

type LengthOfString<T extends string, TRes extends any[] = []> =
    T extends `${infer _}${infer TRight}` ? LengthOfString<TRight, [...TRes, 1]> : TRes['length'];

Solution by knazeri #19121

type LengthOfString<S extends string, Total extends any[] = []> = S extends `${infer F}${infer R}` ? LengthOfString<R, [...Total, F]> : Total['length'];

Solution by CaoXueLiang #19056

// your answers
type LengthOfString<S extends string, Result extends unknown[] = []> = S extends `${infer _R}${infer D}`
                                                                            ? LengthOfString<D, [...Result, unknown]>
                                                                            : Result['length']

Solution by jiaaoMario #17441

type LengthOfString<S extends string, U extends string[] = []> = S extends `${infer P}${infer R}`
  ? LengthOfString<R, [...U, P]>
  : U['length']

Solution by xjq7 #17257

// your answers

type LengthOfString<S extends string, A extends any[] = []> = S extends `${infer J}${infer K}` ? LengthOfString<K, [...A, J]> : A['length']

Solution by Stan-BK #16527

// your answers

type LengthOfString<S extends string, Result extends 0[] = []> = S extends `${infer F}${infer R}`
  ? LengthOfString<R, [...Result, 0]>
  : Result['length']

Solution by humandetail #16445

// your answers
type LengthOfString<
    S extends string,
    T extends readonly string[]=[]> = 
    S extends `${infer R}${infer U}`
    ? LengthOfString<U,[...T,R]>
    : T['length']  ;```

Solution by justBadProgrammer #15868

type LengthOfString<S extends string, Len extends any[] = []> = S extends `${infer F}${infer R}` 
? LengthOfString<R, [...Len, F]> 
: Len['length']; 

Solution by sromic #15847

type LengthOfString<
  S extends string,
  arr extends any[] = []
> = S extends `${infer L}${infer R}` ? LengthOfString<R, [...arr, unknown]> : arr["length"];

Solution by xushuailing #13838