TypeScript advanced type 2 you need to know (summary)

Posted by rndilger on Thu, 20 Jan 2022 06:06:48 +0100

Type inference:

If no type is explicitly specified, TS will infer a type according to the rule of Type Inference:

let myFavoriteNumber = 'seven';      //No mistake
myFavoriteNumber = 7;                //Type 'number' is not assignable to type 'string'.

Note: different from declaring no assignment, declaring no assignment will be set to any value type: any

Union type

Union types use | to separate each type, indicating that it can be assigned to one of them.

let myFavoriteNumber: string | number;  //The type of myFavoriteNumber is allowed to be string or number, but it cannot be any other type.
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;           // No mistake

Note: when TS is not sure which type the variable of a union type is (for example, when defining a method), we can only access the properties or methods common to all types of this union type:

function getLength(something: string | number): number {
    return something.length;    //   Property 'length' does not exist on type 'string | number'.
    //  length is not a common attribute of string and number, so an error will be reported.
    //  However, no error will be reported when accessing the common attributes of string and number, such as return something toString();

When a variable of a joint type is assigned a value, a type will be inferred according to the rules of type inference. At this time, an error will not be reported when accessing the properties of the type.

Object type: Interface

In TS, Interfaces are used to define the type of object.
Interface Interfaces are the abstraction of behavior, and how to act is implement ed by class classes.
The interface in TS is a very flexible concept. It can be used not only to abstract part of the behavior of a class, but also to describe the "Shape of an object".
For example, define an interface Person, and then define a variable tan, whose type is Person. In this way, it is constrained that the shape of tan must be consistent with the interface Person (more or less attributes will report errors):

interface Person {
    name: string;
    age: number;
}
let tan: Person = {
    name: 'tan',
    age: 22
};

Optional attributes (adding attributes that are not in the interface is still not allowed):

When some attributes in an interface are unnecessary, you can set them as optional attributes to avoid them:

interface Person {
    name: string;
    age?: number;       //Set as optional property   
}
let tan: Person = {
    name: 'tan'
};

Any attribute:

Note: if there are any attributes, the types of the determined and optional attributes must be a subset of the types of any attribute.

interface Person {
    name: string;
    [propName: string]: any;        //Define any attribute, take string type, and take any type for attribute value.
}
let tom: Person = {
    name: 'tan',
    gender: 'male'
};

Read only properties:

If it is required that some fields in the object can only be assigned during creation, use readonly to define the read-only attribute (the read-only constraint exists when the object is assigned for the first time, not when the read-only attribute is assigned for the first time):

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}
let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};
tom.id = 9527;      //  Cannot assign to 'id' because it is a constant or a read-only property.

Type of array:

In TS, arrays can be defined in many ways.

Method 1: use "type + square brackets" to represent the array (the type can be any):

let fibonacci: number[] = [1, 1, 2, 3, 5];  //The value of an array can only be of type number
let list: any[] = ['Xcat Liu', 25];  //The value of an array can be of any type

Note: other types are not allowed for the items of the array, and other types are not allowed for the parameters of some methods of the array, such as push()

2. Method 2: array generics:
let fibonacci: Array<number> = [1, 1, 2, 3, 5];

3. Method 3: use the interface to describe the array:

interface NumberArray {
    [index: number]: number;   //As long as the type of index is number, the type of value must be number.
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

Method 4: class array:

Array like objects are not array types, such as arguments.

function sum() {
    let args: number[] = arguments;//Error, arguments missing attribute push
}

// index.ts(2,7): error TS2322: Type 'IArguments' is not assignable to type 'number[]'.
//   Property 'push' is missing in type 'IArguments'.

In fact, common class arrays have their own interface definitions, such as iargements, NodeList, htmlcollection, etc

function sum() {
    let args: IArguments = arguments;
}

Type of function:

In JS, there are two common ways to define functions - Function Declaration and Function Expression.

Function declaration:

Note: an error will be reported if there are too many or insufficient parameters

function sum(x: number, y: number): number {
    return x + y;
}

Function expression:

be careful:

In the type definition of TS, = > is used to represent the definition of a function. On the left is the input type, which needs to be enclosed in parentheses, and on the right is the output type.
In ES6, = > is an arrow function.

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

Define the shape of the function with the interface:

The interface can describe objects and arrays, and is also applicable to functions:

interface SearchFunc {     //Define an interface
    (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;   //Define mySearch type as SearchFunc
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}
// Equivalent to the interface property is the function parameter, and the return value is the interface property value.

Optional parameters:

The same as the optional properties of the interface, use? Represents an optional parameter.
Note: optional parameters must be followed by required parameters, that is, there can be no required parameters after the selected parameters.

function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

Parameter default value:

In ES6, it is allowed to add default values to function parameters. TS will recognize the parameters with default values as optional parameters. Therefore, optional parameters do not have to be followed by required parameters.

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

Remaining parameters:

Similarly, in ES6, you can use... rest to obtain all the remaining parameters in the function:

function push(array: any[], ...items: any[]) { 
    items.forEach(function(item) {  take items Every item push enter array
        array.push(item);
    });
}
let a = [];
push(a, 1, 2, 3);  // a is an array items are the remaining parameters 1, 2, 3

Function overloading: function overloading is not allowed

Allow a function to accept different numbers or types of parameters and do different processing.
Note: TS will preferentially start matching from the first function definition, so if multiple function definitions have inclusion relationship, it is necessary to write the exact definition first. For example:

//Define three overloaded functions to realize the inversion of numbers or strings
//Although this function can be realized by using union types, it can be expressed more accurately by using function overloading! When using, you can see three prompts for this function.
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

Type assertion:

Type Assertion is the type that the developer manually specifies a value:
< type > value or value as type

Note: the value as type must be used in tsx syntax (ts version of jsx syntax of React).

For example, specify a variable of a union type as a more specific type (but not as a type that does not exist in the union type):

// When using union types, you must use the properties common to these types, but there is no such restriction when using type assertion to determine it as a type.
function getLength(something: string | number): number {
    if ((<string>something).length) {    //If the < string > something type is asserted as a string, you can use the unique attribute method of the string.
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

Note: type assertions are not type conversions.

Built in object

There are many built-in objects in JS, which can be directly used as defined types in TS.
Built in objects are objects that exist on the Global scope according to standards. The standards here refer to ECMAScript and other environment standards (such as DOM).

Built in objects of ECMAScript:
The built-in objects provided by ECMAScript standard include Boolean, Error, Date, RegExp, etc. More built-in objects.

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

Built in objects of DOM and BOM:

Built in objects provided by DOM and BOM include Document, HTMLElement, Event, NodeList, etc.
These types are used in TS:

let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});

Topics: Javascript Front-end TypeScript Vue ts