前言

有天面试的时候,面试官问如何写 获取url 参数类型应该怎么写?

  • 当时回答用的是 infer,跟泛型还有递归,但是面试官说哪里需要用到 泛型, 说参数不就是一个string吗,后来就不了了之了。
  • 但回家想了一下,确实应该使用泛型,我的解决思路是没有问题的

解决思路

  • 比如当前 urlhttps://www.baidu.com?key12=0123123&key1=1, 那么我们要获取key12value: 0123123
  • 先截取字符串?之后的值,得到的结果是 key12=0123123&key1=1
  • 然后截取 ${key}=${value} 这个字符串, 得到的结果是 key = key12, value = 0123123&key1=1, 你可以发现value 仍然包含其他值 key value 值, 那么这里我们递归解决就行了
  • 判断逻辑是 如果么有包含 & 那么我们就构建对象,{ [k in key]: value }
  • 最后递归合并对象即可

完整代码

type Merge<F, S> = {[key in keyof F | keyof S]: key extends keyof S ? S[key] : key extends keyof F ? F[key] : never};

type getKeys<T extends string> = T extends `${infer K}?${infer Rest}` ? Rest : ''

type keyToValue<T extends string> = T extends `${infer key}=${infer value}` 
  ? value extends `${infer V}&${infer rest}`
    ? Merge<{[k in key]: V}, keyToValue<rest>> 
    : { [k in key]: value }
  : {}

type A = getKeys<'https://www.baidu.com?key12=0123123&key1=1'>
type B = keyToValue<A>

const url = 'https://www.baidu.com?key12=0123123&key1=1'

function getParameter<T extends string>(url: T): keyToValue<getKeys<T>> {
  const [ , format] = url.split("?");
  const data = format.split("&")
  const result = {} as keyToValue<getKeys<T>>
  data.forEach((_item) => {
    const [key, value] = _item.split("=")
    result[key] = value
  })
  return result
}

const q = getParameter(url)

在线demo

demo