当前位置:网站首页>Pre knowledge reserve of TS type gymnastics to become an excellent TS gymnastics master
Pre knowledge reserve of TS type gymnastics to become an excellent TS gymnastics master
2022-07-06 07:29:00 【Jioho_】
TS Type gymnastics pre knowledge reserve
If you are learning TS, But like me, I just stay in defining types , Definition interface
/type
At the level of , Don't miss this gymnastics type exercise ! type-challenges
When writing this article, I only finished the medium-level questions of gymnastics type ( also 2-3 Tao is not completely solved )
Simply build a question making environment
I like to make a copy of one question , So I clone A copy of type-challenges. And then in type-challenges Created a new folder (my-type-challenges), It's dedicated to TS Artistic Gymnastics
Every time you want to do a question, you just need to remember the number , For example, the first question 13-helloword
. Just input
npm run copy 13
The detailed script is in Jioho/my-type-challenges. After writing the script , You can write code happily
Basic grammar of gymnastics introduction
- The following contents are purely personal opinions , Please point out any mistakes or misunderstandings
Although I say TS Turing Complete ( If a computing system can calculate every Turing computable function , Then this system is Turing complete )
however TS There is not so much grammar , such as if,switch,return And so on. .
TS The most used are Ternary operator
, Judge equal
, Array
, recursive
Some skills will be introduced one by one later
TS Built in advanced types ( Built in Gymnastics )
The first step to getting started is to look at the documentation ( Although I don't like watching , Look not to understand ), But you still need to have a basic understanding utility-types
The current built-in method is as follows :
— | — | — | — |
---|---|---|---|
Partial<Type> | Required<Type> | Readonly<Type> | Record<Keys, Type> |
Pick<Type, Keys> | Omit<Type, Keys> | Exclude<UnionType, ExcludedMembers> | Extract<Type, Union> |
NonNullable<Type> | Parameters<Type> | ConstructorParameters<Type> | ReturnType<Type> |
InstanceType<Type> | ThisParameterType<Type> | OmitThisParameter<Type> | ThisType<Type> |
Uppercase<StringType> | Lowercase<StringType> | Capitalize<StringType> | Uncapitalize<StringType> |
For example, take one that may be used more in the follow-up :
Pick Method
Official website demo:
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
Pick The function of is from an object , Select the required fields , For instance from TODO Only take out title
and completed
If there is no type of gymnastics ,TodoPreview You have to define an additional type
interface TodoPreview {
title:string;
completed: boolean;
}
I encountered this situation in a previous hand training project , Obviously, they are all fields on the same object , In order to adapt to different scenes , Just define a lot of subordinate fields , The key is if you want to change a type , We have to change all of them .. If there is Pick It's all done , Whatever you want pick what
Want to see Pick The implementation is also simple , Pick up any one of them type, Hold down ctrl+ Click on Pick You can see that Pick Realization
The code implementation is as follows :
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
But the first time I saw this code , extends
, keyof
, in
What are these things ? This is the meaning of this article . To look down
Common judgment extends keyword
extends Translation means extension
stay TS Acted as if
and stay XXX Within the scope of
One of the functions of .extends It is usually followed by the ternary operator ( There are exceptions. )
Take up a Son
type mytype1 = 1 extends string ? true : false // false
type mytype2 = '1' extends string ? true : false // true
type mytype2_1 = string extends '1' ? true : false // false
type mytype3 = mytype1 extends any ? 1 : 2 // 1
type mytype4 = [90] extends unknown[] ? true : false // true
type mytype5 = [90] extends string[] ? true : false // false
A few simple examples are given above , A simple explanation :
- 1 Whether to belong to string type obtain false because 1 It's the number type
- ‘1’ Belong to is string Type of The ternary operator is judged as true
- string type Belong to ‘1’ Must be false Of ,string Type range ratio ’1’ Bigger , be not in Belong to The category of the
- mytype1 Belong to any The type is right , because any Include everything ~
- [90] Is a numerical array , Belong to a
unknown
Array of unknown type , This is also true , Because unknown types also contain numeric types - and [90] It doesn't belong to
string[]
The category of the
extends There are also times when the ternary operator is not connected
For example, write a limit string Type of push Method
type StrPush<T extends string[], U extends string> = [...T, U]
type myarr = StrPush<[1, 2, 3], 4>
For example, in this case , It's a direct error . Because I haven't entered StrPush In the judgment of ,T Generics have been constraint by strinig Type ,U Also bound to string type
extends summary
- extends stay TS Of
The body of the function
When I was in, I played Judgment category One of the functions of - In some special places ( For example, when receiving generics , When asserting variable types during function operations ) It plays a role Constraint type The role of
The key of the loop object keyof and in
Just know keyof and in after ,Pick All the keywords of are explained , The first simple question in gymnastics practice MyPick And we're done
- It's still up there demo Code
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
extends The above mentioned , Belong to category judgment / Constraint type , In the generic definition <>
It's obviously for constraint types
keyof It can be understood as Put one object
All in key
extracted .
- Direct use keyof Extract an object to see the effect :
type TodoKeys = keyof Todo
//type TodoKeys = 'title' | 'description' | 'completed'
type testkeys = keyof {[k:number]: any; name:string}
// type testkeys = number | "name"
// Special examples
type Mapish = { [k: string]: boolean; name:string };
type M = keyof Mapish;
// type M = string | number
In the above examples , The first is the best understood , Extract all of key
In the second case ,k As unknown content , extract number As key The scope of the , add “name” So we get number | "name"
A special example is also an example of the official website , Why is there a number type ?
Original words : Note that in this example, M is string | number — this is because JavaScript object keys are always coerced to a string, so obj[0] is always the same as obj[“0”].
translate : Please note that , In this example ,M string | number — This is because JavaScript Object keys are always cast to strings , therefore obj[0] Always with obj[“0”] identical
combination demo ,K extends keyof T
Which means ,K The value range of parameters can only be Todo Key of ('title' | 'description' | 'completed'
), Limit to string , And this 3 One of the keys / Multiple , Only less , Not much
If it's the following
type Mapish = { [k: string]: boolean; name:string };
// K extends keyof Mapish;
K The scope of is string | number type ( Because there is no specific key name , So only No restrictions on specific key names , Only the types are restricted )
Use it like this | Put together ( Or type ) The standard point is called unio Federated data type , Want to cycle these data , You can use in
keyword
go back to demo Explanation
- Pick in Generic T What's coming in is Todo type
K extends keyof T
: K Limit to Todo Key value of ( What's coming in is “title” | “completed” Meet the requirements , Because it can only be less but not more )- P in k It can be understood as loop
- P Will be assigned to title
- Then assign a value completed
- T[P] Meaning and JS Of [] Same value , obtain T[‘title’] => string and T[‘completed’] => completed
- {} It will wrap the result of circulation
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
type TodoPreview = Pick<Todo, "title" | "completed">;
// TodoPreview = {title:string,completed:boolean}
Pick The implementation of is completed .[P in K]
This cycle and we JS The conventional way of writing is very different , It needs to be digested , Everything else should be easy to understand
- Push in , complete Readonly
- as everyone knows readonly Just add readonly Parameters can be
The implementation is as follows :keyof Written in brackets , This is allowed , No matter where these keywords are written, as long as they meet the specifications OK, such as MyReadonly2
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
// This is to paint the snake to the foot , because P It must belong to keyof T Of , It's from keyof T Out of the circulation
// But prove keyof It's not just <> Can be used in
type MyReadonly2<T> = {
readonly [P in keyof T]: P extends keyof T ? T[P] : never
}
Small expansion :
'name' extends keyof T ? true : false
Can also judge T Is there any in this generic object name This attribute
keyof and in Summary
keyof
To get all of an objectKey name
, When the key name is a type , Will be upgraded to the corresponding typein
Is for circulation unio Union type data , Most of them are used to regenerate an object in a loop
JS turn TS – typeof keyword
typeof As from js The world turns into ts The content of the world .
Suppose a scenario , We use one obj Objects are stored as data maps , For example, use a map, Store the status code and return the corresponding msg:
const statusMap = {
200: ' Successful operation ',
404: ' Content not found ',
500: ' operation failed ',
10001: ' Login failure '
}
var status1 = 200
console.log(statusMap[status1]) // Successful operation
var status2 = 10001
console.log(statusMap[status2]) // Login failure
Similar to the above scenario , At this time of the statusMap
in []
The middle value must be 200,404,500,10001 To meet the requirements , stay TS Naturally, we have to agree status
In this range
If not typeof , We can write something like this TS:
type Status = 200 | 404 | 500 | 10001
var status1: Status = 200
console.log(statusMap[status1]) // Successful operation
var status2: Status = 10001
console.log(statusMap[status2]) // Login failure
var status3: Status = 301 // Report red (Type '301' is not assignable to type 'Status')
At this time, suppose we add several key values , that TS You have to change it in synchronization ( It's too troublesome ), use typeof
const statusMap = {
200: ' Successful operation ',
404: ' Content not found ',
500: ' operation failed ',
10001: ' Login failure '
}
type MyStatusMap = typeof statusMap
// Now MyStatus The value of will become
// type MyStatus = {
// 200: string;
// 404: string;
// 500: string;
// 10001: string;
// }
// Then connect. keyof keyword , Extract the key name of the object
type MyStatus = keyof MyStatusMap
// type MyStatus = 200 | 404 | 500 | 10001
// above 2 One step can be abbreviated to one step
type MyStatus2 = keyof typeof statusMap
// type MyStatus2 = 200 | 404 | 500 | 10001
This only requires us to change JS The content of ,TS Will automatically get the new object . It's not enough to return the object , Because what we want to constrain above is the incoming key value ( Want to get the key value , Just above learning keyof
keyword ), You can dynamically obtain all the key values that meet the specifications !
typeof Summary
typeof It is a system that can dynamically put JS Object to TS Key words of .
But there are also limited scenarios , That is, the premise of transformation is this part JS yes Fixed content
. Just like an object mapping in the example , That is the fixed content , And then let TS To deduce
And the packaged code cannot exist TS Of , If you want to implement the back-end interface to dynamically return the content in use typeof , It can't be done
Loops of arrays and strings Inference type infer
infer There are many application scenarios
In a nutshell infer Just one. placeholder Tools for , I stand in this position , As for the content of this position infer Not care , It can be left to the later program to judge
Use simple questions 00014-easy-first Let's explain . Achieve one First
Tool type
Usually get the first element , What we think of is T[0]
Of course. TS This grammar is workable
There can be one item in the test case
Equal<First<[]>, never> // Use T[0] This will report an error , because First<[]> The return is undefined
That is, when this element is declared as undefined when , stay TS Most of them use never
Instead of
The correct answer is as follows :
type First<T extends any[]> = T extends [infer F,...infer Rest] ? F : never
Simply put
infer
Must be in TS Used in function operation ( Defining generic <> in Out of commission , and extends Can )- infer Can cooperate with … Carry out operations
T extends [infer F,...infer Rest]
- The expression means T extends [F,…Rest The remaining values ].T There must be an attribute
F
Array of ,...Rest
It's the rest , not essential ...infer Rest
Is to remove F Other elements are being collected into an array ( This is ES6 The knowledge of the )infer F
It means , I take F In this array placeholder , The contents of the first item of the array , Is being F Account for the
- The expression means T extends [F,…Rest The remaining values ].T There must be an attribute
- Return to the topic , We want to take the first item , So direct return F type
- If T It's an empty array , that extends That step is judged to fail , The natural return is never, Meet the requirements of test cases .
infer Other wonderful uses of
infer It can also traverse strings
Like a The need to cut strings into arrays :
type Split<T extends string, U extends unknown[] = []> =
T extends `${infer F}${infer Rest}` ? Split<Rest, [...U, F]> : U
type testSplit = Split<'123456'>
// type testSplit = ["1", "2", "3", "4", "5", "6"]
among ${infer F}${infer Rest}
It means ,F Occupy the first character ,Rest Occupy the remaining characters , Because it doesn't exist in the string ...
The concept of , therefore Rest Basically, it occupies the remaining characters
A test example like this , Altogether 3 Placeholders ,
type testInfer<T extends string> = T extends `${
infer F}${
infer S}${
infer R}` ? [F, S, R] : T
type testInfer1 = testInfer<'123456'>
// According to the characteristics of placeholders , front F and S To occupy separately 2 Characters , Give the rest R Occupied
// type testInfer1 = ["1", "2", "3456"]
// Make a little change , stay S Add a... After the placeholder 5
type testInfer2<T extends string> = T extends `${
infer F}${
infer S}5${
infer R}` ? [F, S, R] : T
type testInfer3 = testInfer<'123456'>
// F Occupy the first character = 1
// S occupy 2-4, Because in R There was one before 5, therefore S Represents the beginning of the second character to 5 All characters of
// that R It's from 5 Start , To the end , So the results are as follows :
// type testInfer1 = ["1", "234", "6"]
There are many more exercises that will be used later infer , So first understand infer placeholder The characteristics of
infer Summary
infer Equivalent to a keyword occupying a position , Copy the occupied position to the corresponding operation variable .
For arrays or other types , Can also be used … Sum up all the positions to form an array
For strings, this does not exist … To extend the operator , As long as the front occupies a position , The remaining characters will be replaced by the second placeholder
Array usage
An array is TS A very important characteristic of gymnastics , Because in TS There is no concept of addition and subtraction in gymnastics , The operation of addition and subtraction is indispensable in practical operation , Including getting length and so on .
So the array also acts as Counter The role of . There is another very useful trick about array counters , So useful that I think I can write a separate article to analyze it in detail , Now let's briefly introduce the functions of arrays
Let's start with a simple question , Learn the basic properties and usage of arrays 00018-easy-tuple-length
The title gives 2 An array , It was used as const
. We need to find this 2 The length of an array
const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const
const spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT'] as const
type teslaLength = Length<typeof tesla>
type spaceXLength = Length<typeof spaceX>
// answer :
type Length<T extends readonly any[]> = T['length']
Is it simple ?! T['length']
Finished ~
So a very important feature of arrays is , He has length
attribute .
Want to use
length
Premise of attribute :T extends any[]
T The range of types , It must be an array ,any[]
perhapsunknown[]
. Will do , It's an array anyway , There islength
attribute .
Based on this problem of finding length , Extend the , seek 2 The combined length of arrays
type MergeArray<T extends readonly any[],U extends readonly any[]> = [...T,...U]['length']
type arrLength = MergeArray<typeof tesla, typeof spaceX> // 9
Let's have a little interesting topic to experience the role of arrays Questions with medium difficulty 05153-medium-indexof
Achieve one indexOf( There is another point to pay attention to in the original question, which is what we need to pay attention to when judging the type , I will explain later in this article , Now let's look at the simplest implementation ):
Since we need to calculate the index position , Naturally, it involves a Counter The problem of , Look at the answers below
type numberIndex = IndexOf<[1, 2, 3], 1> // The answer you need is 0
type numberIndex2 = IndexOf<[1, 2, 3], 99> // The answer you need is -1
type numberIndex3 = IndexOf<[1, 2, 3], 1> // The answer you need is 0
// The initial template given by the title ( Missing counter )
// type IndexOf<T extends unknown[],U> = any
// For these missing parameters , We can completely fill in a parameter by ourselves , And supplement the default value
type IndexOf2<T extends unknown[], U, C extends 1[] = []> =
T extends [infer F, ...infer Rest] ?
(F extends U ? C['length'] : IndexOf<Rest, U, [...C, 1]>) : -1
The explanation part :
- Because the template given by the title lacks a counter , We can add one C Variable , And the default assignment is
[]
.- As long as there is a default value , It is not required , If it is not required, the test case will not report an error
- T extends and infer Some of them have been explained , If T Not satisfied with at least one
F
When , explain T The array is empty , When it is empty, it means that the result can be obtained- T It's empty , The data has not been matched , Press indexOf The method of should be to return -1
- T If it meets at least one
F
Variable requirements , JudgeF
With the incomingU
Data comparison , If the same, return the length of the current counter ( That is, the index to be calculated )C['length']
- If it doesn't fit , take
Rest
The array continues to loop ( Recursively call IndexOf), meanwhile When calling recursively C It becomes[...C,1]
The array length is incremented 1
[...C,1]
The role of , Is to keep the contents of the original array , Adding a 1, Make the original array length + 1 Counter The effect is achieved
Through a simple expansion operator , Add a 1 Make the length of the array constantly change . Reach the counter / The effect of addition
For example, in the first place. 4182 In the title of , There needs to be a Fibonacci sequence
. The characteristic of Fibonacci sequence is n = (n-1)+(n-2)
. How to realize this addition ? In terms of code, it's […(N-1),…(N-2)].( It doesn't matter if you don't understand , There will be a detailed article later )
Array summary
- As long as the corresponding type extends [] Words , You can use [‘length’] Property to get the length
- Arrays in gymnastics not only act as arrays , It also acts as Counter and Add implementation The role of , Usage is ever-changing
- The accumulation of arrays depends on
Recursive method
The implementation of the , In each recursive process, a new length is passed into the new method ( But recursion is easy to cause memory overflow , such as 02257-medium-minusone This question ). Need a more advanced skill to deal with
as keyword
When explaining arrays above, I saw as const
Appearance , By the way as
stay TS In the use ,as It's just one. Assertion
Let's imagine a scenario like this , There is a variable todo , Set up in order to Todo type , There are corresponding properties
Then... Of a function side effect , Led to my todo Become a string type ( The actual code should avoid this side effect function )
but It just happened , And you can't change , By this time todo Should be string type .todo You also need to call a method , Need to stirng Type of function todoFn(str:string){}
. At this time, it is directly transmitted todo I'm sure there will be an error , The type does not conform to
The solution is todoFn(todo as string)
. It will be easier to understand by looking at the code screenshot below
After I concluded that this type is xxx Type can be used
as
keyword ( Of course, it is not recommended to use ), Try to use TS Type derivation of
stay TS When defining the type of ,as It has other meanings
Like this one
const teslaConst = ['tesla', 'model 3', 'model X', 'model Y'] as const
// const teslaConst: readonly ["tesla", "model 3", "model X", "model Y"]
// use var Variables and const The derivation is the same , But it will leave code hidden trouble , Not recommended
var teslaConst2 = ['tesla', 'model 3', 'model X', 'model Y'] as const
// var teslaConst: readonly ["tesla", "model 3", "model X", "model Y"]
const tesla = ['tesla', 'model 3', 'model X', 'model Y']
// const tesla: string[]
The difference is obvious ,as const Will take out all the values , And become readonly. because const It's really a read-only tag .
however TS Don't eat js Variable type , So I have to pass
as const
To tell TS, I assert that this is a const Array , The elements inside will not be changed , You can traverse the values here
useless as const I only think it's a string[] Array of . This is a big difference
Last
TS The pre knowledge reserve of type gymnastics is probably introduced extends
,infer
,typeof
,keyof and in
, Use of arrays
,as keyword
After understanding the functions of these keywords , complete TS A moderately difficult topic in gymnastics practice A cinch !( At least finish 80% No problem with your title ), The rest 20% Still need to learn more TS Gymnastics skills
This feeling is like if you want to untie a One variable quadratic equation Before , You have to learn the usage and rules of addition, subtraction, multiplication and division . The above introduction is the basic rules of addition, subtraction, multiplication and division , Later, we need to learn more skillful skills to complete more complex TS Artistic Gymnastics
If you are interested, you can go to the homepage to see about TS Other articles on Gymnastics
The above knowledge points are also for me as a TS Some notes summarized by Xiaobai after fumbling for medium-sized topics
Please point out any mistakes or misunderstandings
边栏推荐
- Detailed explanation | detailed explanation of internal mechanism of industrial robot
- 成为优秀的TS体操高手 之 TS 类型体操前置知识储备
- The best way to learn SEO: search engine
- [CF Gym101196-I] Waif Until Dark 网络最大流
- 烧录场景下的源代码防泄密方案分享
- Ali's redis interview question is too difficult, isn't it? I was pressed on the ground and rubbed
- ORACLE列转行--某字段按指定分隔符转多行
- Is the super browser a fingerprint browser? How to choose a good super browser?
- Markdown 中设置图片图注
- If Jerry's Bluetooth device wants to send data to the mobile phone, the mobile phone needs to open the notify channel first [article]
猜你喜欢
Do you really think binary search is easy
Typescript interface and the use of generics
JMeter performance test steps practical tutorial
杰理之如若需要大包发送,需要手机端修改 MTU【篇】
Lesson 12 study notes 2022.02.11
JDBC学习笔记
How to delete all the words before or after a symbol in word
Leecode-c language implementation -15 Sum of three ----- ideas to be improved
[window] when the Microsoft Store is deleted locally, how to reinstall it in three steps
[MySQL learning notes 32] mvcc
随机推荐
2022年Instagram运营小技巧简单讲解
Ble of Jerry [chapter]
Markdown 中设置图片图注
[dictionary tree] [trie] p3879 [tjoi2010] reading comprehension
Three treasures of leeks and Chinese men's football team
TypeScript接口与泛型的使用
Oracle column to row -- a field is converted to multiple rows according to the specified separator
Bugku CTF daily question: do you want seeds? Blackmailed
Jerry's general penetration test - do data transmission with app Communication [article]
Go learning -- implementing generics based on reflection and empty interfaces
If Jerry's Bluetooth device wants to send data to the mobile phone, the mobile phone needs to open the notify channel first [article]
[MySQL learning notes 30] lock (non tutorial)
杰理之BLE【篇】
Typescript interface properties
After the hot update of uniapp, "mismatched versions may cause application exceptions" causes and Solutions
JDBC学习笔记
Méthode d'obtention des propriétés de l'objet JS (.Et [] méthodes)
【mysql学习笔记29】触发器
C - Inheritance - polymorphism - virtual function member (lower)
Ble of Jerry [chapter]