The feed
- What are tool generics?
- Learning tool generics preconditions?
- Learn how to implement official tool generics
- Deepen the review
- conclusion
- The title
After joining the front end team, You Xin realized that his predecessors with rich experience in TS still had many blind spots in TS, so he chose to jump out and learn more in-depth content. Now share with you the tool generics related learning, what is not enough, I hope to communicate with you together. If you don’t want to see it, you can go directly to the official website to learn the official website portal
What are tool generics?
Handle some type specific utility generics, some people also call them utility types because they have some utility properties, like the concept of pure functions.
Learning tool generics preconditions?
Type Type alias
As the name suggests, you can think of it as giving the type a name
type Person = {
name: string
age: number
}
const me: Person = {
name: 'front-end developer'.age: 66,}Copy the code
We can also use it to declare utility generics
type TPickKey<T> = keyof T
interface Person {
name: string
age: number
}
const myKey: TPickKey<Person> = 'name'
// TPickKey<Person> = 'name' | 'age'
// This generic takes the key of the incoming type and puts back the associative type of the key
Copy the code
Conditions in the
In TS 2.8, conditional types were added, and the logic is a ternary operator, so it’s easier to understand
T extends U ? X : Y
Copy the code
infer
To declare a variable and use it, see ReturnType below
Extends inheritance
The extends keyword is often used in the following sections. Extends is similar to the concept of a subset in a mathematical set. Check out this article to get a better understanding of TS. Drill into Typescript’s type system
keyof
The keyof operator, introduced in TypeScript 2.1, can be used to retrieve all keys of a type whose return type is a union type.
interface Person {
name: string
}
type Keys = keyof Person // Keys = "name"
Copy the code
typeof
The typeof operator can be used to get the typeof a variable or object
interface Person {
name: string
}
const me: Person = {
name: 'bugaboo'
}
type MyType = typeof me // MyType = Person
type MyNameType = typeof me.name // MyNameType = string
Copy the code
in
Walking through union types allows you to see the implementation mechanism in this article
– (bar)
The Partial Required code can be used to compare Partial Required to Partial Required.
Learn how to implement official tool generics
Before writing complex tool generics, we must master the basic tools and syntax to better understand and implement them.
Please understand the content of the previous section
First let’s look at some common naming rules, refer to herejava
Generic naming conventions for the
- E – Element (used extensively by the Java Collections Framename)
- K – Key
- N – Number
- T – Type
- V – Value
- S, U, V etc. – 2nd, 3rd, 4th types
- R – Result
- A – Accumulator
Partial
Makes the type passed in optional
interface Person {
name: string
age: number
}
const you: Person = {
name: 'yyds'.age: 18,}const me: Partial<Person> = {
name: 'bugaboo',}// typeof me = {
// name? : string
// age? : number
// }
Copy the code
When I am learning about an unknown thing, I need to understand it as thoroughly as possible. Then will it be traversed deeply?
interface HobbyType {
title: string
desc: string
}
interface Person {
name: string
age: number
hobby: HobbyType[]
}
const you: Person = {
name: 'yyds'.age: 18.hobby: [{ title: 'play game'.desc: 'many games'}}]const me: Partial<Person> = {
name: 'bugaboo'.hobby: [{}] // Type "{}" lacks the following properties of type "HobbyType" : title, descts(2739)
}
Copy the code
implementation
type MyPartial<T> = {
[K inkeyof T]? : T[K] }type MyType = MyPartial<{
name: string
age: number} >Copy the code
parsing
- (
type MyPartial<T>
First, we declare a utility generic - (
K in keyof T
Here,K
Represents theT
Type in thekey
– traversalT
- (
T[K]
) — get the correspondingkey
The type of - (
? :
) — Set it to optional
Readonly
Makes the incoming type read-only
interface Person {
name: string
}
let me: Readonly<Person> = {
name: 'bugaboo'
}
me.name = 'yyds' // "name" cannot be assigned because it is read-only. ts(2540)
Copy the code
implementation
type MyReadonly<T> = {
readonly [K in keyof T]: T[K]
}
type MyType = MyReadonly<{
name: string} >Copy the code
parsing
- (
type MyReadonly<T>
First, we declare a utility generic - (
K in keyof T
Here,K
Represents theT
Type in thekey
– traversalT
- (
T[K]
) — get the correspondingkey
The type of - (
readonly
) — Set it to read-only
Record<K, T>
Apply a type to a union type
interface Person {
name: string
}
type Peoples = Record<'han' | 'Minority', Person>
// type Peoples = {
// Person: Person
// Minority: Person
// }
Copy the code
The implementation.
type MyRecord<K extends keyof any, T> = {
[S in K]: T
}
type MyType = MyRecord<'han' | 'minority', { name: ' '} >Copy the code
parsing
- (
type MyRecord
First, we declare a utility generic - (
<K extends keyof any, T>
) — Pass two arguments - (
K extends keyof any
–K
inheritanceany
, is free, love to spread what spread what, see my example above, I all spread Chinese. - (
S in K
– traversalK
Pick<T, S>
In T, filter out types that are not S
interface Person {
name: string
age: number
}
type MyType = Pick<Person, 'name'>
// type MyType = {
// name: string
// }
Copy the code
implementation
interface Person {
name: string
}
type MyPick<T, S extends keyof T> = {
[K in S]: T[K]
}
type MyType = MyPick<Person, 'name'>
Copy the code
parsing
- (
type MyPick
First, we declare a utility generic - (
<T, S extends keyof T>
) — Pass two arguments - (
S extends keyof T
) — We talked about it earlierkeyof
Is to get the union type, soS
Is inheritedT
的key
The type of union composed of values. - (
K in S
– traversalS
- (
T[K]
– to obtainT
The corresponding type of
Exclude<T, S>
type T = Exclude<1 | 2.2 | 3>
// type T = 1
Copy the code
implementation
type MyExclude<T, S> = T extends S ? never : T
Copy the code
Parsing uses condition types to determine whether T is a subset of S, and then returning never or T automatically distributes conditions for union types
type T = Exclude<1 | 2.2 | 3>
(1 extends 2 | 3 ? : 2 | 3) | (2 extends 2 | 3 ? never : 2 | 3)
Copy the code
So when a union type is passed in, the complement of the two type sets is returned
Omit<T, K>
Delete the corresponding K in T
interface Person {
name: string
age: number
}
type Me = Omit<Person, 'name'>
// type Me = { age: number }
Copy the code
implementation
type MyOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
Copy the code
Parsing uses the above Pick and Exclude combinations
- Find the complement first
keys
- And then I’m going to pick it out of the type set.
ReturnType
Gets the type of the return value of the function
function foo(a: string) :Array<string> {
return [a]
}
type FooReturnType = ReturnType<typeof foo>
// type FooReturnType = string[]
Copy the code
implementation
type MyReturnType<T> = T extends(... arg:any[]) => infer R ? R : any
Copy the code
The infer generation is used to refer to the return type of a function. The extends method is then used to determine whether the function type is a function type, and the corresponding infer generation is returned.
Deepen the review
In fact, I haven’t written all of them. I have only written a few more characteristic tools. The rest, however, is based on a similar implementation with a few tweaks. I’ll list it out, so you can try it out and do it yourself.
- Required – Makes all attributes mandatory
// tip: Partial
type MyRequired<T> = // Imagine for yourself
typeMy = MyRequired<{ name? :string.age: number} >// type My = { name: string }
Copy the code
- Extract – Extracts the intersection of two sets of types
// tip: Exclude
type MyExtract<T, K> = // Imagine
type My = MyExtract<1 | 2.2>
// type My = 2
Copy the code
- NonNullable – Removes null and undefined types
// tip: Take advantage of the union type auto-distribution feature of conditional types
type MyNonNullable = // Imagine
type My = MyNonNullable<string | null | undefined>
// type My = string
Copy the code
- Parameters – Gets the line parameter structure type of the function
// tip: Related to ReturnType
type MyParameters<T> = {
}
type My = MyParameters<(arg: { name: string }) = > string>
// type My = [arg: {
// name: string;
// }]
Copy the code
Some of the less common tools, you can go to the official website and learn the official website portal
conclusion
There are a lot of related articles on the Internet, most of them are source code combination analysis, I am also so. However, according to my learning path, I first summarized basic pre-knowledge, such as infer and conditional judgment, and learned and mastered them in a progressive way. I didn’t write all of them, because I hope, through my article, there is always something to gain, can take the rest of the practice. Maybe people will be resistant at the beginning, especially when it is applied to reality, it will test the ability of deconstruction.
The title
- Gets the type of an element in a type.
eg:
interface Man {
name: string
age: number
}
typeof age = PickType<Man, 'age'>
age = number
Copy the code
additional
Official source: github.com/microsoft/T…