02059-hard-drop-string

Back

type DropString<
  S extends string,
  R extends string
> = S extends `${infer Ch}${infer Rest}`
  ? R extends `${string}${Ch}${string}`
    ? DropString<Rest, R>
    : `${Ch}${DropString<Rest, R>}`
  : "";

Solution by Vampirelee #32635

type DropOne<S extends string, C extends string> =
  S extends `${infer Head}${C}${infer Tail}`
  ? DropString<`${Head}${Tail}`, C>
  : S

type DropString<S extends string, R extends string> = 
  R extends `${infer F}${infer Rest}`
    ? DropString<DropOne<S, F>, Rest>
    : S

Solution by action-hong #32424

type FirstChar<T extends string> = T extends `${infer C}${string}` ? C : never;

type Shift<T extends string> = T extends `${string}${infer R}` ? R : never;

type Trim<T extends string> = T extends `${infer F} ${infer R}`
  ? `${F}${Trim<R>}`
  : T;

type DropString<S extends string, R extends string> = R extends " "
  ? Trim<S>
  : R extends ""
    ? S
    : S extends `${infer First}${FirstChar<R>}${infer Rest}`
      ? DropString<`${First}${Rest}`, R>
      : DropString<S, Shift<R>>;

Solution by idebbarh #30842

type Str2Arr<T> = T extends `${infer A}${infer B}` ? [A, ...Str2Arr<B>] : []
type DropString<S, R> = S extends `${infer A}${infer B}` ? A extends Str2Arr<R>[number] ? DropString<B, R> : `${A}${DropString<B, R>}` : S

Solution by dreamluo-plus #30775

type Includes<S, R extends string> = S extends '' ? false : S extends `${infer A}${R}${infer B}` ? true : false 
type DropString<S, R extends string, U extends string = ''> = S extends`${infer A}${infer B}` ? Includes<R, A> extends true ? DropString<B, R, U> :  DropString<B, R, `${U}${A}`>   : U

Solution by dreamluo-plus #30573

type Includes<S extends string, R> = R extends `${string}${S}${string}` ? true : false
type DropString<S, R> = S extends `${infer A}${infer B}` ? Includes<A, R> extends true ? DropString<B, R> : `${A}${DropString<B, R>}` : ''

Solution by dreamluo-plus #30351

// your answers
type GetStringAry<T> = T extends `${infer First}${infer Rest}` ? [First, ...GetStringAry<Rest>] : []

type First<S> = S extends `${infer First}${infer Rest}` ? First : ''
type Tail<S> = S extends `${infer First}${infer Rest}` ? Rest : ''

type GetRes<S, U> = S extends ''? '' : First<S> extends U ?  `${GetRes<Tail<S>, U>}`: `${First<S>}${GetRes<Tail<S>, U>}`

type DropString<S, R> = GetRes<S, GetStringAry<R>[number]>

Solution by 437204933 #29702

type DropString<S, R, T extends string = ''> =
  S extends `${infer First}${infer Rest}`
  ? DropString<Rest, R, `${T}${R extends `${string}${First}${string}` ? '' : First}`>
  : T

Solution by smileboyi #28134

type StringToUnion<S> = S extends `${infer F}${infer R}`
  ? F | StringToUnion<R>
  : never;

type DropString<
  S,
  R,
  U = StringToUnion<R>
> = S extends `${infer F}${infer REST}`
  ? `${F extends U ? '' : F}${DropString<REST, R, U>}`
  : '';

Solution by JohnLi1999 #25812

2059 - Drop String

We've already done a similar challenge, DropChar which will drop a specific sequence of characters. This one is a bit more complex because it will drop any individual character in the provided pattern. Loops within loops. Turtles all the way down.

🎥 Video Explanation

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

Drop String

🔢 Code

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

type A1 = DropString<'butter fly!', ''>;
type B1 = 'butter fly!';
type C1 = Expect<Equal<A1, B1>>;

type A2 = DropString<'butter fly!', ' '>;
type B2 = 'butterfly!';
type C2 = Expect<Equal<A2, B2>>;

type A3 = DropString<'butter fly!', 'but'>;
type B3 = 'er fly!';
type C3 = Expect<Equal<A3, B3>>;

type A4 = DropString<' b u t t e r f l y ! ', 'but'>;
type B4 = '     e r f l y ! ';
type C4 = Expect<Equal<A4, B4>>;

type A5 = DropString<'    butter fly!        ', ' '>;
type B5 = 'butterfly!';
type C5 = Expect<Equal<A5, B5>>;

type A6 = DropString<' b u t t e r f l y ! ', ' '>;
type B6 = 'butterfly!';
type C6 = Expect<Equal<A6, B6>>;

type A7 = DropString<' b u t t e r f l y ! ', 'but'>;
type B7 = '     e r f l y ! ';
type C7 = Expect<Equal<A7, B7>>;

type A8 = DropString<' b u t t e r f l y ! ', 'tub'>;
type B8 = '     e r f l y ! ';
type C8 = Expect<Equal<A8, B8>>;

type A9 = DropString<' b u t t e r f l y ! ', 'b'>;
type B9 = '  u t t e r f l y ! ';
type C9 = Expect<Equal<A9, B9>>;

type A10 = DropString<' b u t t e r f l y ! ', 't'>;
type B10 = ' b u   e r f l y ! ';
type C10 = Expect<Equal<A10, B10>>;

// ============= Your Code Here =============
type DropString<T, U> =
  T extends `${infer Head}${infer Tail}`
  ? U extends `${string}${Head}${string}`
    ? DropString<Tail, U>
    : `${Head}${DropString<Tail, U>}`
  : '';

// ============== Alternatives ==============
type DropChar<T, U extends string> =
  T extends `${infer Left}${U}${infer Right}`
    ? DropChar<`${Left}${Right}`, U>
    : T;

type DropString<T, U> =
  U extends `${infer Head}${infer Tail}`
  ? DropString<DropChar<T, Head>, Tail>
  : T;

➕ 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 #25352

type ToUnion<T extends string> = T extends `${infer F}${infer R}` ? F | ToUnion<R> : never;

type DropString<S extends string, R extends string> = S extends `${infer F}${infer Rest}` ? `${F extends ToUnion<R> ? `` : F}${DropString<Rest, R>}` : ``;

Solution by E-uler #24968

type StringToUnion<T extends string> = T extends `${infer First}${infer Rest}`
? Rest extends ''
  ? First
  : First | StringToUnion<Rest>
: never

type DropString<S extends string, R extends string> = S extends `${infer First}${infer Rest}`
? First extends StringToUnion<R>
  ? DropString<Rest,R>
  : `${First}${DropString<Rest, R>}`
: ''

Solution by NeylonR #24526

// your answers
type Includes<S, R> = S extends `${infer F}${infer Rest}` ? R extends F ? true : Includes<Rest, R> : false

type DropString<S, R, Acc extends string = ''> = S extends `${infer F}${infer Rest}` ?
Includes<R, F> extends true ? DropString<Rest, R, Acc> : DropString<Rest, R, `${Acc}${F}`> : Acc

Solution by snakeUni #23916

type String2Char<R extends string> = R extends `${infer F}${infer L}` ? F | String2Char<L> : '';
type DropString<S extends string, R extends string, RChar = String2Char<R>> = 
  S extends `${infer CheckChar}${infer LastChar}` 
    ? `${(CheckChar extends RChar ? '' : CheckChar)}${DropString<LastChar, R>}`
    : ''

Solution by litangmm #23607

// your answers
type StringToUnion<S extends string> = S extends `${infer F}${infer R}` ? F | StringToUnion<R> : never;
type DropString<
  S extends string,
  R extends string
> = S extends `${infer F}${infer L}`
    ? F extends StringToUnion<R>
      ? `${DropString<L, R>}`
      : `${F}${DropString<L, R>}`
    : S;

Solution by jxhhdx #23580

type DropString<T extends string, U extends string> = U extends `${infer F}${infer R}`
? `${DropString<T extends `${infer A}${infer B}`?  `${A extends F ? '': A}${DropString<B, F>}`: '',R>}`
: T

Solution by TKBnice #23323

type DropString<S extends string, U extends string> =
  S extends `${infer A}${infer Rest}`
    ? `${U extends `${infer _}${A}${infer _}` ? '' : A}${DropString<Rest, U>}`
    : ''

Solution by drylint #22745

type StringToUnion<T extends string> = T extends `${infer F}${infer Rest}` ? F | StringToUnion<Rest> : undefined;
type DropString<S, R extends string> = S extends `${infer First}${infer Rest}` ? 
`${First extends StringToUnion<R> ? '' : First}${DropString<Rest, R>}` : '';

Solution by Karamuto #22038

// type Drop<S extends string, C extends string>
//     = S extends `${infer F}${C}${infer R}` ? Drop<`${F}${R}`, C> : S

// type DropString<S extends string, R extends string>
//     = R extends `${infer F}${infer R}` ? DropString<Drop<S, F>, R> : S;

type DropString<S extends string, R extends string>
    = S extends `${infer A}${infer B}`
    ? `${R extends `${any}${A}${any}` ? '' : A}${DropString<B, R>}`
    : S

Solution by goddnsgit #21916

type DropString<S extends string, R extends string> = 
  R extends ''
    ? S
    : S extends `${infer First}${infer Rest}`
      ? R extends `${any}${First}${any}` // key point, check if `R` includes `First`
        ? DropString<Rest, R>
        : `${First}${DropString<Rest, R>}`
      : S

playground

Solution by zhaoyao91 #21506

// your answers
type SToUnition<S extends string,A extends any[] = []> = S extends `${infer F}${infer R}` ? SToUnition<R,A extends [...infer Rest] ? [...Rest,F] : [F]> : A[number]
type DropString<S, R extends string, T extends string = ''> = S extends `${infer F}${infer Rest}` ? 
F extends SToUnition<R> ? DropString<Rest,R,T extends `${infer P}` ?  P : F> : DropString<Rest,R,T extends `${infer P}` ?  `${P}${F}` : F> 
: T 

Solution by YqxLzx #21335

type StringToUnion<T extends string> = T extends `${infer F}${infer O}`
  ? F | StringToUnion<O>
  : never

type DropString<S extends string, R extends string> = S extends `${infer F}${infer O}`
  ? `${F extends StringToUnion<R> ? '' : F}${DropString<O, R>}`
  : S

Solution by pengzhanbo #20511

// your answers
type Ste<str, s, r extends string = ""> = str extends `${infer a}${infer b}`
  ? a extends s
    ? Ste<b, s, r>
    : Ste<b, s, `${r}${a}`>
  : r;
type DropString<str, s> = s extends `${infer a}${infer b}`
  ? DropString<Ste<str, a>, b>
  : Ste<str, s>;

Solution by fengjinlong #20293

type StringToUnion<S, Total extends unknown[] = []> = S extends `${infer F}${infer R}` ? StringToUnion<R, [...Total, F]> : Total[number];

type DropString<S extends string, D extends string, Result extends string = ''> = S extends `${infer F}${infer R}`
  ? F extends StringToUnion<D>
    ? DropString<R, D, Result>
    : DropString<R, D, `${Result}${F}`>
  : Result;

Solution by CaoXueLiang #19262

type DropChar<S, R extends string> = S extends `${infer F}${R}${infer E}` ? `${F}${DropChar<E, R>}` : S;
type DropString<S, R extends string> = R extends `${infer F}${infer E}` ? DropString<DropChar<S, F>, E> : S;

Solution by BulatDashiev #16943

type StringToUnion = T extends ${infer R}${infer S} ? R | StringToUnion : never; type DropString<T extends string, R extends string, Q = StringToUnion, S extends string = ''> = T extends ${infer F}${infer Rest} ? F extends Q ? DropString<Rest, R, Q, S> : DropString<Rest, R, Q, ${S}${F}> : S;

Solution by my5201314zwl #16691

type StringToUnion = T extends ${infer R}${infer S} ? R | StringToUnion : never; type DropString<T extends string, R extends string, Q = StringToUnion, S extends string = ''> = T extends ${infer F}${infer Rest} ? F extends Q ? DropString<Rest, R, Q, S> : DropString<Rest, R, Q, ${S}${F}> : S;

Solution by my5201314zwl #16690

// your answers

type DropString<S, R extends string, U = StringToUnion<R>> = S extends `${infer F}${infer Rest}`
  ? F extends U
    ? DropString<Rest, R, U>
    : `${F}${DropString<Rest, R, U>}`
  : S

Solution by humandetail #16483

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

type DropString<
    S extends string, 
    R extends string,
    U extends string=StringToUnion<R> > = 
    S extends `${infer V extends string}${infer W extends string}`
    ? V extends U
    ? DropString<W,R>
    :`${V}${DropString<W,R>}`
    : ''  ;

Solution by justBadProgrammer #15911

type Filter<S extends string, C extends string, Result extends string = ''> = S extends `${infer F}${infer R}` 
? Equal<C, F> extends true 
  ? Filter<R, C, Result> 
  : Filter<R, C, `${Result}${F}`> 
: Result;

type DropString<S extends string, R extends string, F extends string = S> = R extends `${infer First}${infer Rest}` 
? DropString<Filter<S, First>, Rest, Filter<S, First>> 
: F;

Solution by sromic #15848