TypeScript 杂记八 《Query String Parser》

Posted 左手121

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 

以上是关于TypeScript 杂记八 《Query String Parser》的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 杂记八 《Query String Parser》

TypeScript 杂记十二 《Multiply》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记一