This article focuses on understanding TypeScript’s advanced and utility types. In actual TypeScript development, these advanced types and utility types make it easier to build the types we need. For example, in the background login information authentication, we have created a user of the LoginUser type, which contains information like name username, email address, roles, etc. Name may not be mandatory. But it must be of Undefined type when not logged in. It is read-only for permission authentication and mandatory for username name modification.

typeLoginUser = { name? :string;
  email: string;
  roles: string[];
};

type CurrentUser = LoginUser | undefined;

type Muteable<T> = {
  +readonly [P in keyof T]: T[P];
};
type CertUser = Muteable<LoginUser>;
type SuerUser = Required<LoginUser>;
Copy the code

If each type redeclares a new type to satisfy the program, the code will become bloated, whereas if we solve for advanced types, it will become simple and efficient.

Advanced types

The generic

Generics can be understood as a variable whose value is a type. Same as the arguments to the function. It is usually declared with a set of Angle brackets:

// A type with a name attribute
type Cup = {
  name: string;
};
// Declare a function that takes three arguments,
// The first argument is an object that must have the name attribute
// The second argument is set to a property in the object as the first argument
// The third argument is set to the property value of the second argument
constaddAttr = <T extends {name: string}, K, U>(obj: T, attrName: K, attrValue: U) => { const temp: any = {}; temp[attrName] = attrValue; return {... obj, ... temp}; }; // Use Angle brackets after the function name to pass in the qualified type addAttr<Cup, string, number>({name: 'mgdi'}, 'age', 18);Copy the code

The joint type

A federated type is a combination of multiple types, concatenated using the | symbol. When using this type, the value only needs to satisfy one of these types

// Declare type Foo
type Foo = {
  width: number;
}
// Declare a Bar type
type Bar = {
  height: number;
}
// declare a union type of Foo, Bar
type Baz = Foo | Bar;
// Only one of these types is required for assignment
const baz: Baz = {
  width: 20.// height: 10
}
Copy the code

Literal type

Literal type and joint type, the difference is that the joint types with | split type, and literal type integral value.

type Roles = 'student' | 'teacher' | 'kids';
const ading: Roles = "kids";
Copy the code

Enumerated type

An enum type is also typically a collection of key-value pairs, and when its type is used, the assignment can only be one of the declared values.

enum UserRoleType {
  GHOST = "ghost",
  EDITOR = "editor",
  PUBLISH = "publish",
  ADMIN = "admin",}const ading: UserRoleType = UserRoleType.ADMIN;
Copy the code

Cross type

A cross type is a collection of types that are concatenated with ampersand and must satisfy all types at once when used as a value type.

// Declare type Foo
type Foo = { width: number }
// Declare a Bar type
type Bar = { height: number }
// Declare a cross type of Foo, Bar
type Baz = Foo & Bar;
const baz: Baz = {
  width: 3.heght: 4,}Copy the code

Types of assertions

Type assertion is the assertion of an indeterminate type to a self-determined type. A set of Angle brackets “” is usually used in conjunction with the target type T of the assertion, such as user role authentication for the logon at the back end.

import { Request } from 'express';
type CurrentUser = {
  username: string; email? :string;
};
const getCurrentUser = (req: Request): CurrentUser= > {
  return <CurrentUser>req.currentUser;
};
Copy the code

Type the alias

Declare an alias to refer to the current type. It is an alias, not a new type.

type MyString = string;
Copy the code

Ii. Tool types

Partial

Partial: All properties of type T passed in can be made optional.

// type Partial
      
        = { [P in keyof T]? : T[P] | undefined; }
      

type Foo = {
  name: string;
  age: number;
};
const partFoo: Partial<Foo> = {};
Copy the code

Required

Required: Required is the opposite of Partial, which converts all options passed in for type T to Required.

// type Required
      
        = { [P in keyof T]-? : T[P]; }
      

typeFoo = { name? :string; age? :number;
};
const requiredFoo: Required<Foo> = {
  name: 'ading'.age: 18};Copy the code

Readonly

Readonly Readonly converts all properties of construction type T to read-only properties.

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

type Foo = {foo: string};
const foo1: Foo = {foo: 'foo'};
foo1.foo = 'bar';
type ReadonlyFoo = Readonly<Foo>;
const readonlyFoo: ReadonlyFoo = {
  foo: 'foo',}// readonlyFoo.foo = 'bar' //Error
Copy the code

Record

Record<k, T> type copy, setting the construct type T on property K.

// type Record<K extends string | number | symbol, T> = { [P in K]: T; }

type Foo = {foo: string};
type Bar = {
  name: string;
  age: number;
};
type Baz = Record<keyof Bar, Foo>;
const baz: Baz = {
  name: { foo: 'foo' },
  age: { foo: 'foo'}};Copy the code

Pick

PicK<T, K extends Keyof T> Selects a part of the property T

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

type Transportation = {
  name: string;
  speed: number;
  price: number; transportAble? :boolean;
};
type Transportable = Pick<Transportation, 'name' | 'speed'>;
const transportAble: Transportable = {
  name: 'Little Train'.speed: 2};Copy the code

Omit

Omit the < T > K; Omit Omit is the opposite of Pick, which is to Omit selected properties and construct new types using residual types.

// type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }

type Transportation = {
  name: string;
  speed: number;
  price: number; transportAble? :boolean;
};
type MyOmit = Omit<Transportation, 'name' | 'speed'>;
const myomit: MyOmit = {
  price: 20,}Copy the code

Exclude

Exclude<T, K> Removes the same attributes contained in the T type and constructs a new type using the remaining attributes

// type Exclude<T, U> = T extends U ? never : T

type Foo = Exclude<"a" | "b" | "c"."a">;  // "b" | "c"
type Bar = Exclude<"a" | "b" | "c"."a" | "b">;  // "c"
type Baz = Exclude<string | number | (() = > void), Function>;
// string | number
type TExcludeTrain = Exclude<Foo, Baz>; // naver
Copy the code

Extract

Extract<T, K> build a new type from the same type in K

// type Extract<T, U> = T extends U ? T : never

type Foo = Extract<"a" | "b" | "c"."a" | "f">;  // "a"
type Bar = Extract<string | number | (() = > void), Function>;  
// () => void
Copy the code

NonNullable

NonNullable; Remove null and undefined from type T

// type NonNullable<T> = T extends null | undefined ? never : T

type NoNonNullType = NonNullable<string | null | number>;
let noNonNullType: NoNonNullType = 10;
Copy the code

ReturnType

Construct a type that returns a value of type T from the function type

// type ReturnType
      
        any> = T extends (... args: any) => infer R ? R : any
      

type FunReturnBoolean = () = > boolean ; 
type ReturnTypeBoolean = ReturnType<FunReturnBoolean>;
type ReturnNumArr = ReturnType<<T extends U, U extends number[] >() = > T>;
const numbers: ReturnNumArr = [1.2];
Copy the code

InstanceType

Constructs a type from the instance type of the constructor type T

class Human {
  name= 'human beings';
  age= 800;
};
type HumanType = InstanceType<typeof Human>;
let newHuman: HumanType;
let newHuman2: HumanType = new Human();

Copy the code

Three, keywords

keyof

Keyof T; Returns a literal type consisting of all the properties of the constructor type T

type Light = {
  light: number;
  energy: string;
};
type LightKey = keyof Light; // "light" | "energy"
Copy the code

typeof

Typeof k; Returns the type of the variable k

let computer: string[] = ["a"];
type MyComputerType = typeof computer; // string[]
Copy the code

Infer

Infer the T; Pull out some part of the processing of type T as a type variable

type Unpacked<T> =
  T extends (infer U)[] ? U :
  T extends(... args:any[]) => infer U ? U :
  T extends Promise<infer U> ? U :
  T;

type Foo = Unpacked<string>;  // string
type Bar = Unpacked<string[] >;// string
type Baz = Unpacked<() = > string>;  // string
type Qux = Unpacked<Promise<string> >;// string
type Quux = Unpacked<Promise<string> > [];// Promise<string>
type Garply = Unpacked<Unpacked<Promise<string> [] > >;// string
Copy the code

Iv. Official Documents:

www.tslang.cn/docs/releas…