This code runs under version V4.2.3 and defaults to strict mode

Introduction to the

This article is an improvement on the TypeScript tutorial. The original code executes in “non-strict mode.” Here I’ve changed it to code that works in “strict mode” and streamlined many sections.

Hello World

Open the TS online editor and execute the code:

function fn(param: string) {
    return param
}
console.log(fn('Hello World'))
Copy the code

Compiled JS code:

function fn(param) {
    return param;
}
console.log(fn('Hello World'));
Copy the code

Console output:

"Hello World"
Copy the code

The basic concept

  • In TS, use: to specify the type of a variable.

  • TS statically checks types only at compile time, not at run time.

  • Tsconfig. json: noEmitOnError: tsconfig.json: noEmitOnError: tsconfig.json: noEmitOnError

Based on article

1. Raw data type

There are two types of JS: raw data types and object types.

Primitive data types include: Boolean, numeric, string, NULL, undefined, Symbol, and BigInt.

The top five applications in TS:

1.1 Boolean value

Define a Boolean value type using Boolean:

let isDone: boolean = false;
console.log(isDone)
Copy the code

Calling Boolean directly also returns a Boolean type:

let createdByBoolean: boolean = Boolean(1);
Copy the code

But new Boolean() returns a Boolean object:

let createdByNewBoolean: Boolean = new Boolean(1);
Copy the code

Note:

In TS, Boolean is the basic type in JS, and Boolean is the constructor in JS. The other basic types (except null and undefined) are not mentioned here.

1.2 numerical

Define numeric types using number:

let decLiteral: number = 6; let hexLiteral: number = 0xf00d; // let binaryLiteral: number = 0b1010; // let octalLiteral: number = 0o744; // 484 let notANumber: number = NaN; let infinityNumber: number = Infinity;Copy the code

Compile result:

let decLiteral = 6; let hexLiteral = 0xf00d; // let binaryLiteral = 0b1010; // let octalLiteral = 0o744; // 484 let notANumber = NaN; let infinityNumber = Infinity;Copy the code

1.3 the string

Use string to define a string type:

let myName: string = 'pany';
Copy the code

1.4 Void

JS has no concept of void. In TS, void can be used to represent a function that does not return any value:

function logName(): void {
    console.log('pany')
}
Copy the code

It is useless to declare a void variable because you can only assign it undefined: void void

let unusable: void = undefined;
Copy the code

1.5 Null, and Undefined

In TS, null and undefined can be used to define these two primitive data types:

let u: undefined = undefined;
let n: null = null;
Copy the code

2. Any value (Any)

If it is a common type, it is not allowed to change the type during assignment:

let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
// Type 'number' is not assignable to type 'string'.
Copy the code

If it is of any type, however, it is allowed to be assigned to any type:

let myFavoriteNumber: any = 'seven'; myFavoriteNumber = 7; // Compilation succeededCopy the code

It is allowed to access any property or method on any value, and after declaring a variable as any value, any operation on it returns the type of any value:

let anyThing: any = 'pany'; anyThing.myName; anyThing.setName('pany-ang'); // The above code does not have a compile-time error, but does have a runtime errorCopy the code

A variable is recognized as any value type if its type is not specified when it is declared:

let something; something = 'seven'; something = 7; console.log(something); / / 7Copy the code

3. Type inference

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
// Type 'number' is not assignable to type 'string'.
Copy the code

The above code is equivalent to:

let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
Copy the code

That is, TS will infer a type when there is no explicit type specified. This is called type inference.

If defined without an assignment, it is inferred to be of type any, as in the previous section: Any value

4. Union type

The joint type | separated for each type of use:

let myFavoriteNumber: string | number; myFavoriteNumber = 'seven'; myFavoriteNumber = 7; // Compilation succeededCopy the code

The string here | number means, is of type string or number.

When TS is not sure what type a variable of the union type is, it can only access properties or methods that are common to all types of the union type:

function getLength(something: string | number): number { return something.length; / / a compilation error, because the length is not a common attribute} function get string (something: string | number) : string {return something. The toString (); // Compiled successfully}Copy the code

5. Object type (interface)

In object-oriented languages, interfaces and interfaces are abstractions of behavior, and classes are required to implement the behavior.

The interface in TS is a very flexible concept. In addition to abstracting part of the behavior of a class, it is often used to describe the shape of an object.

Interface Person {name: string; age: number; } let pany: Person = {name: 'pany', age: 25};Copy the code

Optional attributes of the interface:

interface Person { name: string; age? : number; // Optional attribute age} let pany: Person = {name: 'pany'}; // Compilation succeededCopy the code

Any attributes of the interface:

interface Person { name: string; age? : number; [propName: string]: any; } let pany: Person = {name: 'pany', gender: 'male'};Copy the code

Note 1: If any attribute is defined and the attribute is of type string (in addition to number, which is often used in class arrays), the type of both the attribute and the optional attribute must be a subset of its attribute value type

interface Person { name: string; age? : number; [propName: string]: string; } let pany: Person = { name: 'pany', age: 25, gender: 'male' }; // Compilation error // Because the type (number) of the optional attribute age is not a subtype of the type (string) of any attributeCopy the code

Note 2: An interface can have only one arbitrary attribute. If the interface has more than one type of attribute, you can use the union type in any attribute

interface Person { name: string; age? : number; [propName: string]: string | number | undefined; } let pany: Person = { name: 'pany', age: 25, gender: 'male' }; // Compilation succeededCopy the code

Read-only property

interface Person { readonly id: number; // readonly Read-only name: string; age? : number; [propName: string]: any; } let pany: Person = { id: 1, name: 'pany', gender: 'male' }; pany.id = 2; // Compilation error: Cannot assign to 'id' because it is a constant or a read-only property.Copy the code

Note: The read-only constraint exists the first time an object is assigned, not the first time a read-only property is assigned

interface Person { readonly id: number; name: string; age? : number; [propName: string]: any; } let pany: Person = { name: 'pany', gender: 'male' }; pany.id = 2; // Error 1: id is not assigned to pany because it is read-onlyCopy the code

6. Array type

6.1 Representation of arrays

The simplest way is to use “type + square brackets” to represent arrays:

let fibonacci: number[] = [1, 1, 2, 3, 5];
Copy the code

But different types are not allowed:

let fibonacci: number[] = [1, '1', 2, 3, 5]; Type 'string' is not assignable to Type 'number'.Copy the code

You can also use the Array generic Array

to represent arrays:

let fibonacci: Array<number> = [1, 1, 2, 3, 5];
Copy the code

Arrays can also be described as interfaces:

interface NumberArray {
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
Copy the code

6.2 class array

Class arrays are not array types, such as arguments:

function sum() { let args: number[] = arguments; } // Error compilingCopy the code

Arguments is actually an array of classes and should not be represented as a normal array, instead it should be represented as an interface:

function sum() {
    let args: {
        [index: number]: number;
        length: number;
        callee: Function;
    } = arguments;
}
Copy the code

In this example, in addition to restricting the type of the value to be a number when the index is of type number, we also restrict the length and callee attributes.

In fact, common class arrays have their own interface definitions, such as IArguments, NodeList, HTMLCollection, etc. :

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

Where IArguments is the type defined in TS, which is essentially:

interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
}
Copy the code

7. Type of function

7.1 Representation method of functions

Function declaration

function sum(x: number, y: number): number { return x + y; } // sum(1, 2) succeeded // sum(1, 2, 3) compiled error because arguments cannot be too many or too fewCopy the code

Functional expression

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

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

Define function shapes with interfaces

interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { return source.search(subString) ! = = 1; }Copy the code

7.2 Optional Parameters

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

Note: Optional parameters must be placed after required parameters; in other words, optional parameters are not allowed to be followed by required parameters

7.3 Default Values of Parameters

function buildName(firstName: string, lastName: string = 'Cat') {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
Copy the code

7.4 Remaining Parameters

With… Represents the remaining parameters, which are actually an array:

function push(array: any[], ... items: any[]) { items.forEach(function(item) { array.push(item); }); } let a: any[] = []; push(a, 1, 2, 3);Copy the code

Note: The remaining parameter can only be the last parameter

7.5 overloading

function reverse(x: number): number; function reverse(x: string): string; function reverse(x: number | string): number | string | void { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); }}Copy the code

Note: TS matches the first function definition first, so if multiple function definitions have inclusion relationships, write the exact definition first.

If this code surprises you, you’re right! Because I also think this writing method, more for “increase readability”……

Type assertion

8.1 grammar

The type used to manually specify a value. Syntax:

Value as typeCopy the code

or

< type > valueCopy the code

The second form cannot be used in TSX, and the syntax of <> is also used in “generics”, so the first syntax is generally used.

8.2 Assert a union type as one of the types

As mentioned earlier (4. Union type), when TS is not sure what type a variable of a union type is, we can only access properties or methods that are common to all types of the union type.

However, in cases where we really need to access a property or method specific to one of the types without determining the type, we need to assert:

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function isFish(animal: Cat | Fish) {
    if (typeof (animal as Fish).swim === 'function') {
        return true;
    }
    return false;
}
Copy the code

Note: Type assertions can only “fool” the TS compiler and cannot avoid runtime errors, which can be caused by abusing type assertions.

8.3 Assert a parent class as a more concrete subclass

Assert a parent class as a more concrete subclass

There is a noteworthy conclusion in the article link above: the TS interface is a type, not a true value, and it will be removed from the compilation result, making it impossible to use Instanceof for runtime judgment.

8.4 Assert any type as any

Sometimes, we’re pretty sure this code won’t go wrong:

window.foo = 1;
Copy the code

But the compiler still tells us that foo does not exist on window.

This is where the assertion is needed:

(window as any).foo = 1;
Copy the code

It most likely hides a true type error, so don’t use as any unless you’re absolutely sure.

8.5 Assert any as a specific type

When you encounter a variable of type any, if you choose to ignore it, you will allow it to breed more any. Choose to improve it by asserting any as an exact type in a timely manner through type assertions, and move our code toward high maintainability.

Function getCacheData(key: string): any {return (window as any). Cache [key]; } // interface Cat {name: string; run(): void; } // declare any as type Cat const Tom = getCacheData(' Tom ') as Cat; tom.run();Copy the code

8.6 Limitations on type assertions

Restrictions on type assertions

ts.xcatliu.com

  • A union type can be asserted as one of these types

  • A parent class can be asserted as a subclass

  • Any type can be asserted to be any

  • Any can be asserted to any type

  • In order for A to be asserted as B, either A is compatible with B or B is compatible with A

In fact, the first four cases are special cases of the last one.

8.7 Double Assertion

Double assertion

Never use double assertion unless you absolutely have to.

8.8 Type Assertion vs type conversion

Type assertion vs type conversion

8.9 Type Assertion vs type declaration

Type assertion vs type declaration

Type declarations are more stringent than type assertions, so to increase the quality of the code, it is best to use type declarations in preference to the as syntax of type assertions.

8.10 Type Assertion vs generics

Type assertion vs generics

9. Declaration documents

When using a third-party library, you need to reference its declaration file to obtain the corresponding code completion, interface prompts and other functions.

Declaration file

10. Built-in objects

JS has many built-in objects that can be used directly as defined types in TS.

Built-in objects for 10.1 ES

// Boolean, Error, Date, RegExp etc. Let b: Boolean = new Boolean(1); let e: Error = new Error('Error occurred'); let d: Date = new Date(); let r: RegExp = /[a-z]/;Copy the code

10.2 Built-in objects for DOM and BOM

/ / Document, HTMLElement, Event, NodeList let allDiv: NodeList = Document. QuerySelectorAll (' div '); document.addEventListener('click', function(e: MouseEvent) { // Do something });Copy the code

10.3 TS core library definition file

TS actually does a lot of the typing work for you using some common methods:

Math.pow(10, '2'); // Error compilingCopy the code

Because math.pow must accept two number arguments, its type is defined as follows:

interface Math {
    pow(x: number, y: number): number;
}
Copy the code

Here’s another example from DOM:

document.addEventListener('click', function(e) { console.log(e.targetCurrent); }); // Error compilingCopy the code

AddEventListener is defined in the TS core library as follows:

interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent { addEventListener(type: string, listener: (ev: MouseEvent) => any, useCapture? : boolean): void; }Copy the code

So e is inferred to be a MouseEvent, and MouseEvent has no targetCurrent attribute, so an error is reported.

Note: The TS core library definition does not include the Node.js section.

10.4 Writing A Node Using TS

Node.js is not part of the built-in object. If you want to write Node.js in TS, you need to import a third-party declaration file:

npm install @types/node --save-dev
Copy the code

Advanced article

TypeScript Introduction Notes (2)