Get a quick start on TypeScript and understand the type system and the problems with JavaScript’s own type system.

Understand the type system

Understand the problems with JavaScript’s own type system. First, understand the following type system

  • Strong versus Weak typing (type safety)

Strong typing: The language level limits that the type of the argument to a function must be the same as the type of the parameter

class Main{
	static void foo(int num){
		System.out.println(num);
	}
	/ / the Main foo (100) / / correct
	/ / the Main foo (" 100 ") / / wrong
}
Copy the code

Weak typing: There is no language level restriction on the types of arguments

function foo(num){
	console.log(num)
}
// Any type can be passed in syntactically without error
foo(100);//ok
foo("100");//ok
Copy the code

Since this distinction between strong and weak types is not defined by an authority at all, strong types are generally described with stronger type constraints, while weak types have few constraints.

Strongly typed languages do not allow arbitrary implicit typing, whereas weakly typed languages allow arbitrary implicit typing of data

The characteristic of variable type that allows change at any time is not the difference between strong and weak types

  • Static versus dynamic typing (type checking)

Static typing: When a variable is declared, its type is unambiguous. After it is declared, its type is not allowed to change

Dynamic typing: The type of a variable can only be specified at run time, and the type of a variable can change at any time

  • JavaScript has its own type system

JavaScript is a weakly typed and dynamically typed language that lacks the reliability of the type system.

Early JavaScript applications were simple, JavaScript was a scripting language, and there was no compilation process (statically typed languages required compilation checks). In large-scale applications, JavaScript’s advantage of flexibility became a disadvantage.

Weakly typed problems:

In a small project, we can set it up by convention, but in a large project, such an agreement will have great potential

//JavaScript weak types cause problems
const obj = {}

// This is a problem. Strongly typed languages throw errors directly at the syntax level
setTimeout(() = > {
    obj.foo();
}, 1000);

If you use a strongly typed language, the function will directly restrict the type of the argument
function sum(a,b){
   return a+b;
}

sum(100.100);/ / 200
sum(100."100");/ / 100100

// Object property names are automatically converted to strings
const obj = {};
obj[true] = 100;
console.log(obj['true']);// Wrong use of object indexer
Copy the code

Advantages of strong typing:

  • Errors are exposed earlier
  • The code is smarter, the code is more accurate
  • Refactoring is more robust
  • Reduce unnecessary type judgments

Flow

Flow Indicates the static type check scheme

Yarn add flow-bin –dev Installation flow

Add a tag to the code: // @flow

Yarn Flow init Initializes a flow

Yarn flow Run the flow command to check the type of the code

/* @flow */
function s(num:number) :void{
    console.log(num);
}
s(123);
Copy the code

JavaScript runs directly without a compile phase, whereas Flow adds a compile phase to JavaScript to check for type errors

  • Flow compilation removes annotations

Generally, the annotation type is only used during the development phase and is not required in the online environment so you need to remove the annotation in the online environment,

Installation module: yarn add flow-remove-types –dev

Run the yarn flow-remove-types SRC -d dist command

The type annotations are removed and the resulting code is as follows, and the code in the dist directory is available for online use

function sum(a:number,b:number){
	return a + b;
}

// Flow code after compilation removes type annotations
function sum(a , b) {
    return a + b;
}

sum(100.100);
sum('100'.'100');
Copy the code
  • babel

Yarn add@babel/core@babel/cli@babel /preset-flow –dev Installs the Babel module to implement compilation to remove the annotation type

Configure the. Babelrc file

{
    "presets": ["@babel/preset-flow"]}Copy the code

Then run: Yarn Babel src-d dist Remove the type annotation from the source code in SRC and put it in the dist directory

  • Flow development tool plug-in

The Flow Language Support plug-in VScode can detect type errors without running the Yarn Flow command

  • The original type
/* The original type @flow */
const a:string = 'foobar';

const b:number = 100;

const b1:number = NaN;

const b2:number = Infinity;

const c:boolean = true;

const d:null = null;

const e:void = undefined;

const f:symbol = Symbol(a);function s() :void{}function ss() :number{
    return 100;
}
Copy the code
  • An array type
/* Array type @flow */
const arr:Array<number> = [1.2.3];/ / < T > generics

const arr2:number[] = [1.2.3.4];

// Array of fixed length
const foo:[string,number] = ['foo'.123];// The first element must be a string and the second element must be a number
Copy the code
  • Object type
/* Object type @flow */
// Define the member types of an object as follows
const obj:{foo:string,bar:number} = {
    foo:'string'.bar : 123
}

// Define the member type above, the member must be defined otherwise error can pass? A: mode member is not required
constobj1:{foo? :string,bar:number} = {
    bar:123
}

// Set type limits for the object property key and value
const obj2:{[string]:string}={}

obj2.key='value';
obj2.age= '14';
Copy the code
  • Function types
/* Function type @flow */
// Set the parameter types and return value types of the function
function s(num:number) :void{
    console.log(num);
}
s(123);

function ss() :number{
    return 100;
}

// The type of the callback function (string,number)=>void the type of the argument and the type of the return value
function foo(callback:(string,number)=>void){
    callback('zce'.123);
}

foo(function(name,num){
    console.log(name,num);
});
Copy the code
  • Special type
/* Special type @flow */
// The literal type a can only be equal to foo
const a:'foo'='foo';

/ / the type can be equal to the 'success' | 'warning' | 'danger'
const type:'success' | 'warning' | 'danger' = 'success';

// You can use more than one type at a time
type StringOrNumber = string | number;

const b : StringOrNumber = '12';/ / 100

constgender:? number =100;/ /? The Maybe type can accept undefined null
Copy the code
  • Any type
/* Any type @flow */

// Mixed strong type can pass arbitrary types
function passMixed(value:mixed){
    // Need to add type judgment
    if (typeof value === 'number') {
        value * value;
    }
    if (typeof value === 'string') {
        value.substr(1);
    }
    
}
passMixed(200);
passMixed('100');

// The weak type any can also represent any type
function passAny(value:any){
    // Any can use any method value is weakly typed
    value * value;

    value.substr(1);
}
passAny(200);
passAny('100');
Copy the code
  • Runtime environment API type
/ * runtime API type https://github.com/facebook/flow/blob/master/lib/dom.js @ flow * /
// The DOM BOM Node's built-in API has some type limitations
const element:HTMLElement | null =  document.getElementById("id");
Copy the code

This is the static type checking scheme provided by Flow, but TypeScript is similar.

TypeScript

TypeScript solves the problem of the JavaScript type system. TypeScript greatly improves code reliability

TypeScript can be supported in any JavaScript runtime environment

Disadvantage 1: The language itself has many concepts

Disadvantage two: at the beginning of the project, it will increase some costs

TypeScript is progressive

TypeScript eventually compiles to JavaScript and supports the ES3 standard

Yarn Add typescript — Add the typescript module to the dev project

Yarn TSC 01-get-start. ts Compiles the TS file. The TSC command compiles the TS file

/* Can be fully coded in javascript */
const hello = (name:string) = > {
    console.log(`hello ${name}`);
}
hello('zce');
Copy the code

The compiled file is as follows:

"use strict";
/* Can be fully coded in javascript */
var hello = function (name) {
    console.log("hello " + name);
};
hello('zce');
//# sourceMappingURL=01-getting-start.js.map
Copy the code
  • TypeScript configuration files

Compile the entire project and create the configuration file :yarn TSC –init

Configuration file: TS there are many other configuration files. You can check the following configuration files on the official website

"target": "es5".// The compiled standard JS code
"module": "commonjs"./ / modular
"outDir": "dist".// The compiled directory
"rootDir": "src".// Source directory
"sourceMap": true.// Source code mapping
"strict": true.// Turn on all strict check options
"lib": ["ES2015"."DOM"].If you want to use the new ES2015 standard, you need to introduce the corresponding standard library, including DOM BOM, etc
Copy the code

The yarn TSC command compiles the entire project, and the compiled JS file is stored in the dist directory

  • Application of primitive types in TS
/* Primitive types in TS */

const a:string = 'foo';

const b:number = 100;//NaN Infinity

const c:boolean = true;//false

// const d:string = null; // Null is not allowed in strict mode

const e:void = undefined;// Null is not allowed in strict mode

const f:null = null;

const g:undefined = undefined;

// If the ES5 library is used, an error will occur when using the ES6 library's new types.
// Solution 1: change to ES2015 standard library;
// Solution 2: "lib": ["ES2015","DOM"]
const h:symbol = Symbol(a);Array;

Promise;

// The DOM API needs to introduce the DOM in lib
console.log();

// The library is the declaration of built-in objects
Copy the code
  • The Object type
export{}

const foo:object = function(){}//[] {} can accept an object array function

// Restrict the members of objects of the object member type
const obj:{foo:number,bar:string} = {foo:123.bar:"string"};
Copy the code
  • An array type
const arr1:Array<number> = [1.2.3,];

const arr2:number[] = [1.2.3,];

/ / -- -- -- -- -- -- -- -- -- accumulation
function sum(. args:number[]){
    // If we use js, we need to determine whether the parameter is of type Number
    //ts only needs to add a numeric type annotation
    return args.reduce((prev,current) = >prev + current,0);
}

/ / sum (1, 2, 3, 4, 'foo');
Copy the code
  • A tuple type

Tuple: a type that specifies the number of elements and the type of the elements. All elements need not be identical

const tuple:[number.string] = [18.' '];// If the type does not match or the number of elements exceeds, an error will be reported

const [age,name] = tuple;

// Tuples are very common now
For example, "entries" get an array of keys, which is a tuple [string,number]
// Note that entries belong to a standard library in ES2017
Object.entries({
    foo:123.bar:456
});
Copy the code
  • Enumerated type

A common way to write a defined type:

const PostStatus={
    Draft:0.Unpublished:1.Published:2
}
Copy the code

How to write an enumeration type

// The default value is: you don't need to specify a value to start at 0
// Enumeration values can be strings, but strings cannot self-grow like numbers. Each enumeration must be assigned a value
// Constant enumerations compile differently than basic enumerations
const enum PostStatus{
    Draft,/ / 0
    Unpublished,/ / 1
    Published/ / 2
}

const post={
    title:"Hello TypeScript".content:"".status:PostStatus.Draft/ / 0 to 1
}

// PostStatus[0]// => Draft
Copy the code
  • Any type
function stringify(value:any){
    return JSON.stringify(value);
}

stringify('100');

stringify(100);
// Any dynamic type ts does not type check it
let foo:any = 'string';

foo = 100;

foo.bar();
Copy the code
  • Function types
// Optional or default parameters must be at the end of the parameter list
function func1(a: number, b? :number. rest:number[]) :string {
  return "func1";
}

func1(100.200);
func1(100);
// func1();
Copy the code

Function expression, the constraint of the callback function in TS can be defined as: (a:number,b:number) => string

// Function expression
// Callback function constraints
const func2 : (a:number,b:number) = > string =  function(a:number,b:number) :string{
    return 'func2';
}
Copy the code
  • Implicit type inference

TypeScript automatically recommends types, but does not allow them to change once they are identified

let age = 18;// Deduce for number

// age = 'number'; / / an error

let foo;// No assignment is of type any
// You can give values of any type without syntax error
foo = 100;

foo = 'string';

// Add a more intuitive type for each variable
Copy the code
  • Types of assertions
const nums = [100.200.199.112];

const res = nums.find(i= >i>1000);// Infer that the res may not be found

// const square = res * res;
const num1 = res as number;// Tell the compiler it must be number and don't worry

const num2 = <number>res;
Copy the code
  • interface

Interfaces can dictate the structure of an object, they can dictate what members there are. TS is just a constraint that doesn’t really make any sense when it’s written in JavaScript just like a normal object

interface Post {
  title: string;
  content: string;
  // Optional memberssubtitle? :string;
  // Read-only member
  readonly summary:string;
}

function printPost(post:Post){
    console.log(post.title);
    console.log(post.content);
}
// The subtitle attribute is optional and may not be passed in
printPost({title:'hello'.content:'a javascript'.summary:'12'});

const hello: Post = {
  title: "hello".content: "a javascript".summary:'A JavaScript'
};

hello.summary = "123";The summary attribute is read-only and cannot be modified
Copy the code

The key type of the dynamic member and the type definition of the value must be the same or an error will be reported

interface Cache{
    [prop:string] :string //[prop:string] -> key type :string -> value type
}

const cache:Cache = {}
cache.foo = "value";
// cache.bar = 123; / / an error
Copy the code
  • Class Class

Class describes an abstract feature of a class of objects that ES6 previously simulated through functions + archetypes

Class is an added feature in ES6, and TypeScript adds an access modifier to class based on ES6. Class attributes must be declared first and must have an initial value.

class Person{
    // Class attributes must have an initial value or an assigned value in the constructor
    public name:string;// The default is public
    private age:number;//private Private properties can only be accessed within the class
    protected readonly gender:boolean;// Protected is accessible only to subclasses
    //readonly The read-only property is not allowed to be modified if it is initialized by = or the constructor
    constructor(name:string ,age:number){
        TS specifies that the declared property must have an initial value, either after = or in the constructor
        this.name = name;
        this.age = age;
        this.gender = true;
    }
    sayHi(msg:string){
        // this.gender = false;
        console.log(`I am The ${this.name} is age:The ${this.age}`);
    }
    logSay(){
        this.sayHi('Hello'); }}class Student extends Person{
    / / the constructor declares the private external were not allowed to instantiate the class with all
    private constructor(name:string,age:number){
        super(name,age);
        console.log(this.gender);
        //
        // this.gender = false;
    }
    // Can be returned to an external call via an internal new instance
    static create(name:string,age:number){
        return newStudent(name,age); }}const tom = new Person('tom'.18);
console.log(tom.name);
// console.log(tom.gender);
// console.log(tom.age);

// const jake = new Student('jake',18);
const jake = Student.create('jake'.18);
Copy the code

Class implements the interface with the following code:

interface Eat{
    eat(foo:string) :void
}
interface Run{
    run(distance:number) :void
}

class Person implements Eat.Run{
    eat(foo:string) :void{
        console.log('Eat with grace${foo}`);
    }
    run(distance:number) :void{
        console.log(Walk upright${distance}`); }}class Animal implements Eat.Run{
    eat(foo:string) :void{
        console.log('Gollum gollum${foo}`);
    }
    run(distance:number) :void{
        console.log(Crawl `${distance}`); }}Copy the code

Abstract classes can contain concrete implementations of methods

abstract class Anima{
    eat(foo:string) :void{
        console.log(Eat `${foo}`);
        
    }
    // Abstract method
    abstract run(d:number) :void;
}

class Dog extends Anima{
    // Implement the abstract method of the superclass
    run(d: number) :void {
        console.log(` go:${d}`); }}Copy the code
  • The generic

TypeScript also introduces the concept of generics

function crateNumberArray(len:number,value:number) :number[]{
    //
      
        Stores data of type number
      
    const arr = new Array<number>(len).fill(value);
    return arr;
}

const res = crateNumberArray(3.100);
/ / res = > [100100100]

// Create data of type string
function crateStringArray(len:number,value:string) :string[]{
    //
      
        Stores data of type number
      
    const arr = new Array<string>(len).fill(value);
    return arr;
}

// Use generics to solve the redundancy in the above code

function createArray<T> (len:number,value:T) :T[]{
    const arr = new Array<T>(len).fill(value);
    return arr;
}

createArray<number> (1.100);
createArray<string> (10.'10');
Copy the code

The mixed development of TS and JS involves old code and other logic, so type declaration is needed here. For example, if the third-party module we use is not implemented by TS, then type declaration of the module is needed

Lodash third-party libraries, for example, provide type declaration files that need to be installed. NPM install @types/lodash

import {camelCase} from 'lodash';

// The query-string module already contains the type declaration module
import qs from 'query-string';

// qs.parse();

// Declare the type of the function
// declare function camelCase (input:string) : string;

// NPM install @types/lodash or install the type declaration module

const r = camelCase('hello worle');
Copy the code