前言
有天面试的时候,面试官问如何写 获取url 参数类型应该怎么写?
- 当时回答用的是 infer,跟泛型还有递归,但是面试官说哪里需要用到泛型, 说参数不就是一个string吗,后来就不了了之了。
- 但回家想了一下,确实应该使用泛型,我的解决思路是没有问题的
解决思路
- 比如当前 url为https://www.baidu.com?key12=0123123&key1=1, 那么我们要获取key12跟value: 0123123
- 先截取字符串?之后的值,得到的结果是key12=0123123&key1=1
- 然后截取 ${key}=${value}这个字符串, 得到的结果是key = key12,value = 0123123&key1=1, 你可以发现value仍然包含其他值keyvalue值, 那么这里我们递归解决就行了
- 判断逻辑是 如果么有包含 &那么我们就构建对象,{ [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)
