当前位置:网站首页>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
边栏推荐
- RHCE day 3
- Leetcode48. Rotate image
- [Galaxy Kirin V10] [server] set time synchronization of intranet server
- RHCE - day one
- Summary of several job scheduling problems
- 【Day2】 convolutional-neural-networks
- Debug:==42==ERROR: AddressSanitizer: heap-buffer-overflow on address
- Tables in the thesis of latex learning
- Rhcsa12
- Button wizard business running learning - commodity quantity, price reminder, judgment Backpack
猜你喜欢

Introduction to tree and binary tree

If the uniapp is less than 1000, it will be displayed according to the original number. If the number exceeds 1000, it will be converted into 10w+ 1.3k+ display
![[Galaxy Kirin V10] [desktop] cannot add printer](/img/a6/28e4aa31e805a018e6db2b32ca1be0.jpg)
[Galaxy Kirin V10] [desktop] cannot add printer

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

Rhcsa day 10 operation

Dynamic memory management

Sword finger offer 05 (implemented in C language)

Recursion and divide and conquer strategy
![[Galaxy Kirin V10] [server] KVM create Bridge](/img/a4/a35a276d13e194cefc547607c59f00.jpg)
[Galaxy Kirin V10] [server] KVM create Bridge

C language structure to realize simple address book
随机推荐
[Galaxy Kirin V10] [server] KVM create Bridge
【Day1】 deep-learning-basics
Rhcsa learning practice
C language - stack
Basic principle of servlet and application of common API methods
基于线性函数近似的安全强化学习 Safe RL with Linear Function Approximation 翻译 2
Linked list operation can never change without its roots
Button wizard business running learning - commodity quantity, price reminder, judgment Backpack
【Day1】 deep-learning-basics
Talk about scalability
Software sharing: the best PDF document conversion tool and PDF Suite Enterprise version sharing | with sharing
[Galaxy Kirin V10] [desktop] cannot add printer
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
Jianzhi offer 04 (implemented in C language)
Debug:==42==ERROR: AddressSanitizer: heap-buffer-overflow on address
DDL statement of MySQL Foundation
Quick sort (C language)
/*Write a loop to output the elements of the list container in reverse order*/
Static comprehensive experiment ---hcip1
Occasional pit compiled by idea