1. Mapping type
- Mapping types are TS’s ability to map one type to another.
For details on the built-in advanced types, see the official lib.es5.d.ts. Note that all type operations operate on objects that are types
Start by defining two simple types:
// Response data
interface Res {
code: number;
msg: string;
data: any; errMsg? :string;
}
type ResCode = 200 | 300 | 400 | 500;
Copy the code
1. Optional properties
Grammar:
type partial = Partial<T>
Copy the code
Use:
type ResPartial = Partial<Res>
/ / equivalent
typeResPartial = { code? :number; msg? :string; data? :any; errMsg? :string;
}
Copy the code
Principle:
type Partial<T> = {
[P inkeyof T]? : T[P]; };Copy the code
Key operations in”, “keyof T”, “?”
2. Mandatory properties
Grammar:
type required = Required<T>
Copy the code
Use:
type ResRequired = Required<T>
/ / equivalent
type ResRequired = {
code: number;
msg: string;
data: any;
errMsg: string;
}
Copy the code
Principle:
type Required<T> = {
[P inkeyof T]-? : T[P]; };Copy the code
Key operations “in”, “keyof T”, “-?”
3. Read-only properties
Grammar:
type readonly = Readonly<T>;
Copy the code
Use:
type ResReadonly = Readonly<res>
/ / equivalent
type ResReadonly = {
readonly code: number;
readonly msg: string;
readonly data: any;
readonlyerrMsg? :string;
}
Copy the code
Principle:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Copy the code
Key operations “in”, “keyof T”
4. Select/pick attributes
Grammar:
type pick = Pick<T, k in keyof T>
Copy the code
Use:
type ResPick = Pick<Res, "code" | "data">
/ / equivalent
type ResPick = {
code: number;
data: any;
}
Copy the code
Principle:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
Copy the code
Key operations “extends”, “keyof T”, “in”
5. Dynamic structure
Grammar:
type record = Record<K extends keyof any, T>
Copy the code
Use:
type recordString = Record<string.any>
/ / equivalent
type recordString = {
[x: string] :any;
}
type recordReq = Record<"id" | "token" | "data".any>
/ / equivalent
type recordReq = {
id: any;
token: any;
data: any;
}
Copy the code
Principle:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Copy the code
Key operations “extends”, “keyof any”, “in”
6. Exclude attributes
Grammar:
type exclude = Exclude<T, U>
Copy the code
Use:
type excludeResCode = Exclude<ResCode, 200>
/ / equivalent
type excludeResCode = 300 | 400 | 500
Copy the code
Principle:
type Exclude<T, U> = T extends U ? never : T;
Copy the code
Key operations “extends”, “?” , “never”
Note: Unlike Pick, Extract operates on associative types. Pick can operate on both object types and associative types
7. Extract attributes
Grammar:
type extract = Extract<T, U>
Copy the code
Use:
type extractResCode = Extract<ResCode, 200 | 300>;
/ / equivalent
type extractResCode = 200 | 300;
Copy the code
Principle:
type Extract<T, U> = T extends U ? T : never;
Copy the code
Key operations “extends”, “?” , “never”
Note: This rule differs from Exclude
8. Ignore attributes
Grammar:
type omit = Omit<T, K>
Copy the code
Use:
type omitRes = Omit<Res, 'code' | 'msg'>
/ / equivalent
type omitRes = {
data: any; errMsg? :string;
}
Copy the code
Principle:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Copy the code
Key operations “extends”, “keyof any”, “Exclude”
9. Exclude null and undefined
Grammar:
type nonNullable = NonNullable<T>
Copy the code
Use:
type Msg = string | null | number | undefined;
type MsgNonNullable = NonNullable<reMsgsMsg>;
/ / equivalent
type nonNullable = string | number;
Copy the code
Principle:
type NonNullable<T> = T extends null | undefined ? never : T;
Copy the code
Key operations “extends”, “?” , “never”
Get the return type of the function parameter
Grammar:
type parameters = Parameters<T>;
Copy the code
Use:
interface ShowInfo {
(msg: string.type: number) :string;
}
type parameters = Parameters<ShowInfo>;
/ / the result
type parameters = [msg: string.type: number]
Copy the code
Principle:
type Parameters<T extends(... args:any) = >any> = T extends(... args: infer P) =>any ? P : never;
Copy the code
Key operations “extends”, “?” , “infer”
Get the function return type
Grammar:
type returnType = ReturnType<T>;
Copy the code
Use:
interface ShowInfo {
(msg: string.type: number) :string;
}
type returnType = ReturnType<ShowInfo>;
/ / the result
type returnType = string
Copy the code
Principle:
type ReturnType<T extends(... args:any) = >any> = T extends(... args:any) => infer R ? R : any;
Copy the code
Key operations “extends”, “?” , “infer”
Keywords/operators
In the first, mapping type lists the commonly used built-in type mapping. Of course, if you look at the key operations, you’ll see that the principles are expanded with keywords/operators of the “keyof”, “extends”, “infer”, “in” and other types.
1, keyof
Gets the combined type of all keys of type T; You can manipulate interfaces, classes, and primitive data types
type ResKeyof = keyof Res;
/ / equivalent
type ResKeyof = "code" | "msg" | "data" | "errMsg";
/ / class
class Animal {
constructor() {}
eat() {}
walk(){}}type AnimalType = keyof Animal; // "eat" | "walk"
// For example, get object attributes and array indexes
function getProto<T.K extends keyof T> (obj: T, key: K) {
return obj[key];
}
Copy the code
2, extends
Used for type inheritance or conditional judgment, when used with the trinary operator (? 🙂 use conditional judgment; Everything else is inheritance.
/ / inheritance
interface Person {
name: string;
age: number;
}
interface Student extends Person {
grade: number | string;
}
/ / equivalent
interface Student {
name: string;
age: number;
grade: number | string;
}
// Determine, such as the built-in NonNullable
;
type NonNullable<T> = T extends null | undefined ? never : T;
Copy the code
Actually when extends and generics use type constraints, for example:
// keyof any => string | number | symbol
function showInfo<T extends keyof any> (info: T) {
return info;
}
Copy the code
Its nature can also be interpreted as inheritance, we can keyof any return is a joint type string | number | symbol; T extends keyof any through extends. That is the type of info is string | number | symbol joint type. So when introduced to a non string | number | type of symbol would be an error.
3, infer
Type inference in conditional types. Isn’t this the current use of extends for TS conditional statements? Currently, type conditions are judged only when extends matches the trinary operator (? 🙂 when used together. So infer can be used without the extends and trinary operator (? :).
For example, the built-in type InstanceType
type InstanceType<T extends new(... args:any) = >any> = T extends new(... args:any) => infer R ? R : any;
Copy the code
The first extends is a type constraint because it is used with generics and is not used with the ternary operator. The constraint type T is a class. The second extends forms a conditional judgment with the triadic operation, so you can infer using the Infer type. Infer is used when the constructor of InstanceType returns the result. Objective To infer the instance type of T. Interested friends can try parsing Parameters
4, in
The public property name used to traverse the target type; Similar to the for in operation.
/ / such as Record
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Copy the code
With what you’ve learned about extends and Keyof, add extends to your generic use. It follows that extends is used to constrain type K. In is used to traverse the target type; So P is the name of the property in type K. Combined with the type constraint, P can only be string, number and symbol.
In can also iterate through enumerations.
enum Color {
Red,
Green,
Blue,
}
type ColorType = {
[P in Color]: string;
};
Copy the code
5, is
Used to determine whether a variable belongs to a type. Can be interpreted as “!!” Operation.
// Syntax: {variable} is {type}
function isNull(val: unknown) :val is null {
return val === null;
}
Copy the code
Note: The use of IS is for variable and type operations
If there are mistakes, welcome to correct them. Learn together and make progress together