This article takes a brief look at the use and implementation of utility generics. Most of these generic interface definitions are syntactic sugar (shorthand) and can even be found in the typescript package lib.d.ts. The latest version of typescript (2.9) includes most of them. I’ll point out what I didn’t include.

Partial

Partial is used to make an attribute passed in optional. First we need to understand the two keywords keyof and in. Keyof can be used to get all the keys of an object interface. Such as

interface Foo {
  name: string;
  age: number
}
type T = keyof Foo // -> "name" | "age"
Copy the code

In, on the other hand, can iterate over enumerated types, for example

type Keys = "a" | "b"
type Obj =  {
  [p in Keys]: any
} // -> { a: any, b: any }
Copy the code

Keyof generates enumerated types, and in uses enumerated types to traverse, so they’re often used together. Look at the Partial source code

type Partial<T> = { [P in keyof T]? : T[P] };Copy the code

Keyof T retrieves the names of all attributes of T, then in iterates, assigning the values to P, and finally T[P] retrieves the values of the corresponding attributes. Student: In the middle? We know what Partial means.

Required

Required makes the attribute passed in mandatory. The source code is shown below

type Required<T> = { [P in keyof T]-? : T[P] };Copy the code

We found an interesting use -? Well, it makes sense to represent the alternatives, right? Remove to make this type mandatory. And that corresponds to a plus, right? This meaning is naturally related to -? Instead, it was used to make properties optional.

Mutable (not included)

Similarly, there are also + and -, and the point here is not to add or subtract between variables but to add or subtract readonly. The following code removes readonly for all attributes of T, or you can write the opposite.

type Mutable<T> = {
  -readonly [P in keyof T]: T[P]
}
Copy the code

Readonly

Change the attribute passed in to a read-only option, source code below

type Readonly<T> = { readonly [P in keyof T]: T[P] };
Copy the code

Record

Convert the values of all attributes in K to type T

type Record<K extends keyof any, T> = { [P in K]: T };
Copy the code

Pick

Take a set of properties of K from T

type Pick<T, K extends keyof T> = { [P in K]: T[P] };
Copy the code

Exclude

A condition type was introduced in TS 2.8, as shown below

T extends U ? X : Y
Copy the code

If T is a subtype of U, return X, otherwise return Y

You can even combine more than one

type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    T extends undefined ? "undefined" :
    T extends Function ? "function" :
    "object";
Copy the code

Conditions are automatically distributed for federated types, such as T extends U? X, Y, T may be A | B type, the actual situation becomes (A extends U? X : Y) | (B extends U ? X : Y)

With that in mind, let’s look at tool generics

Take a look at the Exclude source code

type Exclude<T, U> = T extends U ? never : T;
Copy the code

Combined with the instance

type T = Exclude<1 | 2, 1 | 3> // -> 2
Copy the code

2. Based on the code and examples, we can infer that the function of Exclude is to find out the elements that are not in U from T. In a more semantic way, it is to Exclude U from T

Extract

According to the source code, we infer that Extract is used to Extract T contained in the U element, another more close to the semantics of the statement is to Extract U from T source code as follows

type Extract<T, U> = T extends U ? T : never;
Copy the code

Omit anything

Use the previous combination of Pick and Exclude to realize the function of ignoring some attributes of the object, the source code is as follows

Type Omit = Pick<T, Exclude<keyof T, K>> // Use type Foo = <{name: string, age: number}, 'name'> // -> {age: number }Copy the code

ReturnType

Infer before reading the source code, we need to learn about the keyword infer. In conditional type statements, infer can be used to declare and use a type variable to obtain the return type of a function. The source code is shown below

type ReturnType<T> = T extends ( ... args: any[] ) => infer R ? R : any;Copy the code

Infer R here means to declare a variable to bear the return value type of the signature of the incoming function. In short, infer R is used to fetch the return value type of the function for later use. The specific use

function foo(x: number): Array<number> {
  return [x];
}
type fn = ReturnType<typeof foo>;
Copy the code

AxiosReturnType (not included)

Development often uses AXIos to encapsulate API layer requests, usually a function that returns an AxiosPromise

. Now I want to get its Resp type, which we can write based on our knowledge of generics from the last tool.

Import {AxiosPromise} from 'axios' type AxiosReturnType<T> = T extends (... args: any[]) => AxiosPromise<infer R> ? R: any // use type Resp = AxiosReturnType<Api> // pass your Api request function in the generic parameterCopy the code

Refer to the link

  • Github.com/Microsoft/T…
  • Stackoverflow.com/questions/3…
  • www.rickcarlino.com/2017/02/27/…
  • Github.com/Microsoft/T… ‘s-new-in-TypeScript#typescript-28
  • zhuanlan.zhihu.com/p/39620591