09616-medium-parse-url-params

Back

type ParseUrlParams = T extends ${string}:${infer Str} ? Str extends ${infer S}/${infer E} ? S | ParseUrlParams : Str : never

Solution by rookiewxy #34676

type Explode<T extends string, U extends string> = T extends `${infer L}${U}${infer R}`
  ? L | Explode<R, U>
  : T extends ""
  ? never
  : T;

type ParseUrlParams<T extends string> = T extends ""
  ? never
  : Explode<T, "/"> & `:${string}` extends `:${infer P}`
  ? P
  : never;

Solution by yukicountry #34349

type ParseUrlParams = T extends ${any}:${infer E} ? E extends ${infer SS}/${infer EE} ? SS | ParseUrlParams :E:never

Solution by rookiewxy #34281

type ParseUrlParams<T extends string> = T extends `${string}:${infer suffix}` ? (suffix extends `${infer R}/${infer rest}` ? R | ParseUrlParams<rest> : suffix) : never

Solution by ouzexi #34111

type ParseUrlParams<T extends string, Result extends any[] = []> = T extends `${string}${':'}${infer Rest}` 
? Rest extends `${infer Start}${'/'}${infer End}`
  ? ParseUrlParams<End,[Start, ...Result]>
  : [Rest, ...Result][number]
: Result[number]

Solution by PiligrimStas #33799

maybe tricky ...

type ParseUrlParams<T, Ret extends string[] = []> = 
`${T &  string}/` extends `${any}:${infer Param}/${infer Rest}`
  ? ParseUrlParams<Rest, [...Ret, Param]>
  : Ret[number];

Solution by sunupupup #33445

type ParseArg<T extends string> = T extends `:${infer W}` ? W : never

// Tail recursion optimized
// supoort very long URL
type ParseUrlParams<T extends string, Res = never> =
  T extends `${infer Arg}/${infer Rest}`
  ? ParseUrlParams<Rest, Res | ParseArg<Arg>>
  : Res | ParseArg<T>

Solution by bkmashiro #33279

// your answers
type ParseUrlParams<T extends string> = `/${T}/` extends `${infer A}/:${infer B}/${infer C}`
? B | ParseUrlParams<C>  : never

Solution by pea-sys #33241

type ParseUrlParams<T> = 
  T extends `${infer F}/${infer R}` 
    ? T extends "" | "/"
      ? never 
      : F extends `:${infer S}`
        ? S | ParseUrlParams<R>
        : ParseUrlParams<R>
    : T extends `:${infer S}`
      ? S
      : never

Solution by vangie #32197

type ParseUrlParams<T extends string, Res extends string[] = []> = 
  T extends `${infer Layer}/${infer Rest}` ? 
  Layer extends `:${infer L}` ?
  ParseUrlParams<Rest, [...Res, L]> :
  ParseUrlParams<Rest, Res> :
  T extends `:${infer L}` ?
  [...Res, L][number] :
  Res[number]

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

type cases = [
  Expect<Equal<ParseUrlParams<''>, never>>,
  Expect<Equal<ParseUrlParams<':id'>, 'id'>>,
  Expect<Equal<ParseUrlParams<'posts/:id'>, 'id'>>,
  Expect<Equal<ParseUrlParams<'posts/:id/'>, 'id'>>,
  Expect<Equal<ParseUrlParams<'posts/:id/:user'>, 'id' | 'user'>>,
  Expect<Equal<ParseUrlParams<'posts/:id/:user/like'>, 'id' | 'user'>>,
]

Solution by gearonix #31400

type ParseUrlParams<T extends string> = 
`/${T}/` extends `${infer A}/:${infer B}/${infer C}`  ? B | ParseUrlParams<C>  : never

Solution by TheHighlandss #31126

type ParseUrlParams<T extends string> = T extends `${infer F}/${infer R}`
  ? (F extends `:${infer S}` ? S : never) | ParseUrlParams<R>
  : T extends `${string}:${infer R}`
  ? R
  : T;

Solution by moonpoet #31019

type AllParts<S extends string> = S extends `${infer H}/${infer P}`
  ? H | AllParts<P>
  : S

type ParseUrlParams<T extends string, P = AllParts<T>> = P extends `:${infer X}` ? X : never

Solution by psmolak #31008

type Split<T extends string> = T extends "" ? [] : T extends `${infer F}/${infer T}` ? [F, ...Split<T>] : [T];

type ParseUrlParams<T extends string> = keyof {
  [key in Split<T>[number] as key extends `:${infer R}` ? R : never]: true
}

Solution by kakasoo #30899

// your answers
type GetPathParam<S> = S extends `:${infer Param}` ? Param : never
type ParseUrlParams<T extends string> = T extends `${infer L}/${infer R}` ? GetPathParam<L> | ParseUrlParams<R> : GetPathParam<T>

Solution by Kakeru-Miyazaki #30897

type SplitString<
  S extends string,
  D extends string,
  B extends string = '',
  U extends unknown[] = [],
> = S extends `${infer F}${infer Rest}`
  ? F extends D
    ? SplitString<Rest, D, '', [...U, B]>
    : SplitString<Rest, D, `${B}${F}`, [...U]>
  : [...U, B];

type ParseUrlParams<T extends string, U extends string[] = SplitString<T, '/'>, R extends unknown[] = []> = U extends [
  infer F extends string,
  ...infer Rest extends string[],
]
  ? F extends `:${infer SS}`
    ? ParseUrlParams<T, [...Rest], [...R, SS]>
    : ParseUrlParams<T, [...Rest], [...R]>
  : R[number];

Solution by leejaehyup #30864

type ParseUrlParams<T, U extends any[] = []> = T extends `${string}:${infer A}` ? A extends `${infer B}/${infer C}` ? ParseUrlParams<C, [...U, B]> : ParseUrlParams<'', [...U, A]> : U[number] 

Solution by dreamluo-plus #30684

// 1.FormatterString用来格式化字符串, 去掉/
type FormatterString<T> = T extends `${infer First}/${string}` ? First : T
// 2.GetFirstParam 用来获取第一个匹配的参数
type GetFirstParam<T> = T extends `${infer First}:${string}` ? FormatterString<First> : FormatterString<T>
// 3.如果匹配就传入联合类型且递归, 最后返回
type ParseUrlParams<T, List = never> = T extends `${string}:${infer Other}` ? ParseUrlParams<Other, List | GetFirstParam<Other>> : List

Solution by xiahouwei #30582

type ParseUrlParams<T> = T extends `${string}:${infer R}`
  ? R extends `${infer P}/${infer L}`
    ? P | ParseUrlParams<L>
    : R
  : never

Solution by XkSuperCool #30353

// your answers
type ParseUrlParams<T> = 
T extends `${string}:${infer ID}` ? ID extends `${infer U}/${infer Rest}` ? U | ParseUrlParams<Rest> : ID : never

Solution by kerolossamir165 #29957

type ParseUrlParams<
  T extends string,
  R extends string = never
> = 
T extends `${string}:${infer S}/${infer L}`?
  ParseUrlParams<L,R | S>:
  T extends `${string}:${infer S}`?
    R | S
    : R

Solution by jiangshanmeta #29709

type ParseUrlParams<T> = T extends `${any}:${infer S}`
  ? S extends `${infer K}/${infer Rest}`
    ? K | ParseUrlParams<Rest>
    : S
  : never

Solution by Sun79 #29681