TypeScript 杂记八 《Query String Parser》

TypeScript 杂记八 《Query String Parser》

Query String Parser

思路

  • 求出每一个 k=v,可能会出现下边的情况:
    • aaa=1&bbb
    • aaa
type ParserHelper<
  T extends string,
  R extends Record<string, unknown[]> = {}
> = T extends `${infer A}&${infer B}`
  ? A extends `${infer K}=${infer V}`
    ? ParserHelper<B, Merged<R, K, V>>
    : // aaa=1&bbb 情况,直接设置 bbb=true
      ParserHelper<B, Merged<R, A, true>>
  : T extends `${infer K}=${infer V}`
  ? Merged<R, K, V>
  : T extends ""
  ? R
  : // aaa 情况,设置 aaa=true
    Merged<R, T, true>;
  • 合并值
    • 考虑到存在多个值的情况,需要采用元组形式。我们这里统一都采用元组形式
    • 先不考虑数据重复的情况
    • 如果 V 是一个空字符串则将 V 设置成 true
    • 将 R[K] 和 V 进行合并
    • 将 R 中对应的 K 移除
    • 将新的 R 和新的 K V 合并
type Merged<
  R extends Record<string, unknown[]>,
  K extends keyof R,
  V
> = V extends ""
  ? Merged<R, K, true>
  : Omit<R, K> & Record<K, R[K] extends unknown[] ? [...R[K], V] : [V]>;
  • 元组中的值去重
    • 使用 K 来定义元组中所有的值(不重复,其结果为 "1" | "2" | true 形式)
    • R 用来存储最终的结果
    • 如果 A 在 K 中,则表示重复,继续下一步
    • 如果 A 不在 K 中,则表示唯一,新的 K 变成了 K | A,R 变成了 [...R, A]
    • 当 T 为空的时候,返回结果 R。如果 R 里边只有一个值,则返回对应的这个值
type Deduplication<
  T extends unknown[],
  K = "",
  R extends unknown[] = []
> = T extends [infer A, ...infer B]
  ? A extends K
    ? Deduplication<B, K, R>
    : Deduplication<B, K | A, [...R, A]>
  : R extends [infer U]
  ? U
  : R;

完整示例

type Deduplication<
  T extends unknown[],
  K = "",
  R extends unknown[] = []
> = T extends [infer A, ...infer B]
  ? A extends K
    ? Deduplication<B, K, R>
    : Deduplication<B, K | A, [...R, A]>
  : R extends [infer U]
  ? U
  : R;

type Merged<
  R extends Record<string, unknown[]>,
  K extends keyof R,
  V
> = V extends ""
  ? Merged<R, K, true>
  : Omit<R, K> & Record<K, R[K] extends unknown[] ? [...R[K], V] : [V]>;

type ParserHelper<
  T extends string,
  R extends Record<string, unknown[]> = {}
> = T extends `${infer A}&${infer B}`
  ? A extends `${infer K}=${infer V}`
    ? ParserHelper<B, Merged<R, K, V>>
    : ParserHelper<B, Merged<R, A, true>>
  : T extends `${infer K}=${infer V}`
  ? Merged<R, K, V>
  : T extends ""
  ? R
  : Merged<R, T, true>;

type Parser<T extends Record<string, unknown[]>> = {
  [K in keyof T]: Deduplication<T[K]>;
};

type QueryStringParser<T extends string> = Parser<ParserHelper<T>>;

测试

type A =
  QueryStringParser<"a=&a=1&a=1&a=1&b=2&c=3&a=1&b=2&c=3&a=1&b=2&c=3&c=3&a=&a=1&b=5&x=12&xxx&aaa&bbb">;
// type A = {
//   a: [true, '1']
//   b: ['2', '5']
//   c: '3'
//   x: '12'
//   xxx: true
//   aaa: true
//   bbb: true
// }

type B = QueryStringParser<"aaasad">;
// type B = { aaasad: true }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值