rimo030 / type-challenges

Collection of TypeScript type challenges with online judge
https://tsch.js.org/
MIT License
3 stars 0 forks source link

no - 151 Query String Parser #125

Open rimo030 opened 4 months ago

rimo030 commented 4 months ago
type AddValue<O extends object, K extends keyof O, V> = {
  [key in keyof O] : key extends K 
    ? O[key] extends any[]
      ? V extends O[key][number]
        ? O[key]
        : [...O[key], V]
      : O[key] extends V
        ? O[key]
        : [O[key], V]
    : O[key]
}

type ParseValue<T extends string, L extends object> = T extends `${infer K}=${infer V}`
  ? K extends keyof L
    ? AddValue<L, K, V>
    : L & Record<K, V>
  : T extends keyof L
    ? AddValue<L, T, true>
    : L & Record<T, true>

type _ParseQueryString<S extends string, L extends object = {}> = S extends `${infer F}&${infer R}`
  ? _ParseQueryString<R, ParseValue<F, L>>
  : ParseValue<S, L>

type ParseQueryString<S extends string> = S extends '' 
  ? {}
  : Omit<_ParseQueryString<S>, never>
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<ParseQueryString<''>, {}>>,
  Expect<Equal<ParseQueryString<'k1'>, { k1: true }>>,
  Expect<Equal<ParseQueryString<'k1&k1'>, { k1: true }>>,
  Expect<Equal<ParseQueryString<'k1&k2'>, { k1: true, k2: true }>>,
  Expect<Equal<ParseQueryString<'k1=v1'>, { k1: 'v1' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k1=v2'>, { k1: ['v1', 'v2'] }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k2=v2'>, { k1: 'v1', k2: 'v2' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k2=v2&k1=v2'>, { k1: ['v1', 'v2'], k2: 'v2' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k2'>, { k1: 'v1', k2: true }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k1=v1'>, { k1: 'v1' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k1=v2&k1=v1'>, { k1: ['v1', 'v2'] }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k2=v1&k1=v2&k1=v1'>, { k1: ['v1', 'v2'], k2: 'v1' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k2=v2&k1=v2&k1=v3'>, { k1: ['v1', 'v2', 'v3'], k2: 'v2' }>>,
  Expect<Equal<ParseQueryString<'k1=v1&k1'>, { k1: ['v1', true] }>>,
  Expect<Equal<ParseQueryString<'k1&k1=v1'>, { k1: [true, 'v1'] }>>,
]