当前位置:网站首页>TS type gymnastics: illustrating a complex advanced type
TS type gymnastics: illustrating a complex advanced type
2022-07-04 10:36:00 【PHP Development Engineer 】
Today, let's do a difficult gymnastics , It uses pattern matching 、 structure 、 Recursive equivalent routine , It is very helpful to improve the level of type programming .
The advanced types we want to implement are as follows :

Its type parameter is the parameter string query string, The parsed parameter object will be returned , If you have a parameter with the same name , Will merge the values .
Don't worry about realizing , Let's first review the relevant types of gymnastics :
Type gymnastics foundation
Pattern matching
Pattern matching refers to matching a pattern type with a type to extract some of its types to infer Declared local variables .
Like extracting a=b Medium a and b:

This pattern matching routine is in the array 、 character string 、 Functions and other types have many applications .
structure
Mapping types are used to generate index types , The index or index value can be modified during the generation process .
For example, specify key and value To generate an index type :

recursive
TypeScript Advanced types support recursion , It can handle the problem of uncertain quantity .
For example, the inversion of an indefinite length string :
type ReverseStr< Str extends string, Result extends string = '' > = Str extends `${infer First}${infer Rest}` ? ReverseStr<Rest, `${First}${Result}`> : Result; Copy code 
Learn about pattern matching 、 structure 、 After what recursion is , You can start implementing this complex high-level type ParseQueryString 了 :
Thought analysis
Suppose there is one query string: a=1&a=2&b=3&c=4.
We should first divide it into 4 part : That is to say a=1、a=2、b=3、c=4. This is extracted through the pattern matching mentioned above .
Each part can be further processed , Extract key value Constructed as an index type , such as a=1 Can be extracted by pattern matching a、1, Then construct the index type {a: 1}.
That's it 4 Index types {a:1}、{a:2}、{b:3}、{c:4}.
Just combine it into one , When merging, if there are the same key Value , Put it in the array .
The final index type is generated :{a: [1,2], b: 3, c: 4}
The whole process is like this :

The first step is not to know how many a=1、b=2 such query param, So we need to recursively do pattern matching to extract .
This is the implementation idea of this advanced type .
Let's write about it in detail :
Code implementation
We implement it in the order shown in the figure above , First extract query string Each of them query param:

query param The quantity is uncertain , So use recursion :
type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}` ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>> : ParseParam<Str>; Copy code Type parameter Str For pending query string.
Extract the first one through pattern matching query param To infer Declared local variables Param in , The rest of the string is put in Rest in .
use ParseParam To deal with it Param, The rest of the recursive processing , Finally, combine them , That is to say MergeParams<ParseParam<Param>, ParseQueryString> .
If the pattern match does not meet , Explain that there is still one last query param 了 , Also used ParseParam Handle .
Then implement each one separately query param Of parse:

This is pattern matching extraction key and value, Then construct an index type :
type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}` ? { [K in Key]: Value } : {}; Copy code Here, the syntax of mapping type is used to construct index type .
Let's test this first ParseParam:

Finish each query param The analysis of , Then merge them together :

The merged part is MergeParams:
type MergeParams< OneParam extends object, OtherParam extends object> = { [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam ? Key extends keyof OtherParam ? MergeValues<OneParam[Key], OtherParam[Key]> : OneParam[Key] : Key extends keyof OtherParam ? OtherParam[Key] : never} Copy code The merging of the two index types also requires the construction of a new index type using the syntax of the mapping type .
key Is taken from both, that is key in keyof OneParam | keyof OtherParam.
value There are two situations :
- If both index types exist key, Merge , That is to say MergeValues.
- If only one of the index types has , Then take its value , That is to say OtherParam[key] perhaps OneParam[Key].
When merging , If both are the same, either one will be returned , If it's not the same , Merge it into an array and return , That is to say [One, Other]. If it was an array , That is the merging of arrays [One, ...Other].
type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other]; Copy code Under test MergeValues:

such , We have implemented the whole advanced type , Overall test :

This case applies recursion synthetically 、 Pattern matching 、 Structured routine , It's more complicated .
You can look at the complete code with reference to this figure :

type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}` ? { [K in Key]: Value } : {};type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];type MergeParams< OneParam extends object, OtherParam extends object> = { [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam ? Key extends keyof OtherParam ? MergeValues<OneParam[Key], OtherParam[Key]> : OneParam[Key] : Key extends keyof OtherParam ? OtherParam[Key] : never}type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}` ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>> : ParseParam<Str>;type ParseQueryStringResult = ParseQueryString<'a=1&a=2&b=2&c=3'>; Copy code summary
We first reviewed 3 The routines of three types of gymnastics :
- Pattern matching : A type matches a pattern type , Extract some of these types to infer Declared local variables
- structure : Construct a new index type by mapping the syntax of the type , The index and value can be modified during construction
- recursive : When dealing with types with uncertain quantities , You can only process one at a time , Hand over the rest to do
Then use these routines to achieve a ParseQueryString Complex advanced types .
If you can implement this high-level type independently , It shows that you have a good grasp of the routines of these three types of gymnastics .
Last
If you think this article is of little help to you , Point a praise . Or you can join my development communication group :1025263163 Learn from each other , We will have professional technical questions and answers
If you think this article is useful to you , Please give our open source project a little bit star:http://github.crmeb.net/u/defu Thank you for !
PHP Learning manual :https://doc.crmeb.com
Technical exchange forum :https://q.crmeb.com
边栏推荐
- 【Day1】 deep-learning-basics
- 按键精灵打怪学习-识别所在地图、跑图、进入帮派识别NPC
- Static comprehensive experiment ---hcip1
- [200 opencv routines] 218 Multi line italic text watermark
- DML statement of MySQL Foundation
- From programmers to large-scale distributed architects, where are you (2)
- Si vous ne connaissez pas ces quatre modes de mise en cache, vous osez dire que vous connaissez la mise en cache?
- Map container
- Rhcsa12
- [Galaxy Kirin V10] [server] grub default password
猜你喜欢

Rhcsa12

Huge number (C language)

What is an excellent architect in my heart?

Occasional pit compiled by idea

Sword finger offer 05 (implemented in C language)
If you don't know these four caching modes, dare you say you understand caching?

Time complexity and space complexity
![[Galaxy Kirin V10] [server] iSCSI deployment](/img/60/13f43dc584c0768965d60811768948.jpg)
[Galaxy Kirin V10] [server] iSCSI deployment

VLAN part of switching technology

Debug:==42==ERROR: AddressSanitizer: heap-buffer-overflow on address
随机推荐
[Galaxy Kirin V10] [server] system partition expansion
PHP programming language (1) - operators
How do microservices aggregate API documents? This wave of show~
Dos:disk operating system, including core startup program and command program
Native div has editing ability
【Day1】 deep-learning-basics
[Galaxy Kirin V10] [server] iSCSI deployment
leetcode1-3
The future education examination system cannot answer questions, and there is no response after clicking on the options, and the answers will not be recorded
[Galaxy Kirin V10] [server] failed to start the network
Check 15 developer tools of Alibaba
Time complexity and space complexity
Knapsack problem and 0-1 knapsack problem
On binary tree (C language)
The time difference between the past time and the present time of uniapp processing, such as just, a few minutes ago, a few hours ago, a few months ago
System. Currenttimemillis() and system Nanotime (), which is faster? Don't use it wrong!
From programmers to large-scale distributed architects, where are you (2)
Static comprehensive experiment ---hcip1
Dichotomy search (C language)
OSPF summary