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