TypeScript

Is to solve the JavaScript type problem

  1. TypeScriptGreatly improve the reliability of your code
  2. JavaScriptProblems with your own type system

Before we get to TypeScript, let’s talk about type checking

  1. Strong and weak types
  2. Static versus dynamic typing
  3. JavaScriptProblems with your own type system
  4. FlowStatic type checking scheme
  5. TypeScriptLanguage specification and basic application

Personal Understanding:

  1. Implicit type conversions for what problem are not allowed in strongly typed languages **(the argument type in a function must be the same as the parameter type)**

    The advantage of strong typing

    • Mistakes are exposed earlier
    • Code is smarter, slower and more accurate
    • Refactoring is more reliable
    • Reduce unnecessary judgments
  2. Weakly typed languages allow any data to be implicitly typed **(there are no restrictions on what type parameters must be passed)**

  3. Strong types do not allow arbitrary implicit type conversions, while weak types do

  4. The feature that variable types are allowed to change at any time is not strong, after all, because of type differences

Strong vs. weak

Strongly typed: The language level restricts the argument types of functions to be the same as the parameter types

class Main {
    static void foo(int num) {
        System.out.println(num);
    }
    
    public static void main(String[] args) {
        Main.foo(100); // ok
        
        Main.foo("100"); // error "100" is a string
        
        Main.foo(Integer.parseInt("100")); // ok}}Copy the code

Weak typing: The language level does not restrict the types of arguments

function foo(num) {
    console.log(num)
}
foo(100) // ok
foo('100') // ok
foo(parseInt('100')) // ok

Copy the code
  • Because this distinction between strength and weakness is not the definition of any authority at all;

  • Strong types have stronger type constraints, and weak types have few constraints, right

The type system

Static versus dynamic typing

  1. Static typing: when a variable is declared, its type is unambiguous; after it is declared, its type cannot be changed
  2. Dynamic typing: Variable types are known at run time and can change at any time
var foo = 100
foo = 'bar' // ok
console.log(foo)

Copy the code

It can also be said that variables in dynamically typed languages have no type, whereas values stored in variables are typed

Type safety is classified into strong and weak types

Type checking is divided into static type and dynamic type

As shown in figure

JavaScript type system features

Weakly typed and dynamically typed

Js types are described in one word: capricious lack of reliability in the type system –> unreliable

? Why isn’t JavaScript strongly typed/statically typed

  1. The early days of JavaScript were simple to use
  2. JavaScript does not compile
  3. Select weak/dynamic type
  4. On a large scale, this [advantage] becomes a weakness

Weak type problems

demo

/ / 01
const obj = {}
obj.foo()
Type exceptions cannot be found until runtime
/ / = = = = = = = = = = = = = = = = = = = = = =
/ /.
function sum(a, b) {
    return a + b
}
console.log(sum(100.100)) / / 200
console.log(sum(100.'100')) / / 100100
/ / = = = = = = = = = = = = = = = = = = = = = =
// 03
const obj = {}
obj[true] = 100 // is automatically converted to a string

console.log(obj['true'])

Copy the code

Flow.js type checking tool

Quick learning

The first way

//yarn add flow-bin --dev(project installation)/yarn add flow-bin -g(global installation)
//yarn init --yes // global
// To use flow, note the following:
// Add @flow at the top of the file and disable vscode syntax validation
// Shutdown method:
// Set -> Search javascript validate to turn it off
// @flow
function sun(a:number,b:number){
    return a+b
}
sun(100.100)
sun(100."100")
// Run YARN flow
//yarn flow stop
// Initialize flow
//yarn flow init Add a. Flowconfig file
[ignore]

[include]

[libs]

[lints]

[options]

[strict]

// Execute yarn flow again


// Written js files cannot be executed using Node
// Install a plugin at this time
//yarn add flow-remove-types -gAfter installation, run yarn flow-remove-types.(no import required). -d(convert output directory) dist(output directory)// Usually put in SRC
yarn flow-remove-types src -d dist
Copy the code

Another way to do it

Install Babel

//yarn add @babel/core --dev //

//yarn add@babel /cli // This is Babel cli tool which allows us to compile directly using the command line tool

//yarn add@babel /preset-flow --dev // Convert a plug-in of the flow type

// Install it together
//yarn add @babel/core @babel/cli @babel/preset-flow --dev
// After installation, you can use the Babel command to compile js code

// Add the Babel configuration file.babelrc
{
    "presets": ["@/babel/preset-flow"]}// Execute the command
//yarn Babel SRC -d dist // convert all SRC files to dist
// install the plugin in vscode
//Flow Language Support allows errors to be displayed directly on development tools
Copy the code

Folw cases and syntax

Type Inference

/** * Type inference **@flow* * /
function sun(n) {
    return n * n
}
sun('100')
Copy the code

Annotations

/** * type annotation **@flow* * /
// 1. Function parameters and backarguments
function square(n: number) {
    return n * n
}
/ / 2. Variables
let num: number = 100
// num = 'string'
// 3. No return value is marked as void
function foo() :void {
    // return 'string'
}
Copy the code

Primitive Types of Primitive

/** * Original type **@flow* * /
const a: string = 'foo'
// There are three types of number :Infinity 100 NaN
const b: number = Infinity
const c: boolean = true
const d: null = null
// Undefined in flow is represented by void
const e: void = undefined
const f: symbol = symbol
Copy the code

Array Types Array Types

/** * Array type **@flow* * /
// Represents an array of all numbers
/ / generics
const arr1:Array<number>=[1.2.3]
const arr2:number[]=[1.2.3]
/ / yuan group
const foo:[String,number]=['foo'.100]
Copy the code

Object Types Object Types

/** * Object type **@flow* * /
const obj1:{foo:String.bar:number}={foo:"string".bar:222}
// Optional type
// Foo is optional
constobj2:{foo? :String.bar:number}={foo:"string".bar:222} 
// Both key-value pairs must be strings

const obj3={[string]:string}={}
obj3.key1="value1"
obj3.key2="value2"
Copy the code

Function types

/** * Function types **@flow* * /
// void returns no value
function foo(cllback: (string, number) => void) {
    cllback("string".100)}/ / call
foo(function (str, n) {
    str => string
    n => number
})
Copy the code

Special type

/** * Special type **@flow* * /
// Literal type (usually not used alone)
const a: "foo" = "foo"  // The a variable can only be a string of foo
/ / | means or
const type: "success" | "warning" | "danger"
type StringOrNumber = string | Number
const b: StringOrNumber = 'string'

// Possible types
// Can accept null or undefined in addition to number
const gender: ? number = null
Copy the code

Mixed &&any any type

/**
 * mixed any
 * 
 * @flow* * /
/ / mixed can receive all types of string | number | Boolean
// Mixed is a strong type. Any is weak
// Is strongly typed
function pass(value:mixed){

}
pass("string")
pass(100)

// The difference is that any is weak and mixed is strong
function passMixed(value: mixed) {
    value.substr(1)
    value * value
    // There will be an error
    // Change to the following
    if (typeof value == 'value') {
        value.substr(1)}if (typeof value == 'number') {
        value * value
    }
}
passMixed('string')
passMixed(100)

// -----------------------

function passAny(value: any) {
    value.substr(1)
    value * value
}
passAny('string')
passAny(100)

Copy the code

Runtime ENVIRONMENT API -> Built-in objects

const element: HTMLElement | null = document.getElementById('app') // The string must be passed

// https://github.com/facebook/flow/blob/master/lib/core.js
// https://github.com/facebook/flow/blob/master/lib/dom.js
// https://github.com/facebook/flow/blob/master/lib/bom.js
// https://github.com/facebook/flow/blob/master/lib/cssom.js
// https://github.com/facebook/flow/blob/master/lib/node.js


Copy the code

typescript

The installation

Yarn init –yes Initial initialization

Yarn Add typescript — Dev is installed in development projects, not globally

// You can install JavaScript standard syntax to write
const hello = (neme:string) = > {
    console.log(`hhllo, ${name}`);

}
hello(100) // This is a string, not a number
Copy the code

Yarn Tsc.\ 01getting.ts runs

In most cases, simply run YARN TSC and convert ts to JS in the DIST file

The configuration file

Yarn TSC --init Generates a tsconfig.json compilerOptions target. Dist rootDir: the folder in which our source code is configured SRC sourceMap: whether source code mapping is enabled strict: To enable strict mode, run the TSC command to compile the entire project YARN TSCCopy the code

Basic grammar

// Can be written using JavaScript standard syntax
const hello = (neme:string) = > {
    console.log(`hhllo, ${name}`);

}
hello('100')
Copy the code

Primitive Primitive Types

const s: string = 'foo'
const b: number = 100
const c: boolean = true
// const d:boolean=null
const e: void = undefined
const f: null = null
const g: undefined = undefined
const h: symbol = Symbol(a)Copy the code

Typescript sets Chinese prompts

yarn tsc --locale zh-CN 
Copy the code

An error occurs when scoping two. Ts files with the same amount of variables

/ / scope
// The first method
// (function(){
// const a=2
/ /}) ()

const a=2
// The second method
export{}
Copy the code

Object Type Object Types

Not just objects

/ / the object type
// object is not just a value object
export {} // Make sure there are no member conflicts with other examples
Function [] {} function [] {
const foo:object=function(){}

// You can use a literal if you want a normal object
const obj:{foo:number.bar:string} = {foo:123.bar:"string"}
Copy the code

Array Types Array Types

export {} // Make sure there are no member conflicts with other examples

// Two representations of array types

const arr1: Array<number> = [1.2.3]

const arr2: number[] = [1.2.3]

/ / case -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

// If it is JS, you need to check whether every member is a number
// use TS, the type is guaranteed, do not add type judgment
function sum (. args:number[]) {
  return args.reduce((prev, current) = > prev + current, 0)
}

sum(1.2.3) / / = > 6
Copy the code

Tuple Types

Specify the number of elements and an array of each element type, not necessarily the same type

export {} // Make sure there are no member conflicts with other examples

const tuple: [number.string] = [18.'zce']

// Access the tuple's data
// The first method
// const age = tuple[0]
// const name = tuple[1]
// The second array deconstruction method is extracted
const [age, name] = tuple

// ---------------------

const entries: [string.number=] []Object.entries({
  foo: 123.bar: 456
})

const [key, value] = entries[0]
// key => foo, value => 123


Copy the code

Enum Type Enum Types

  1. Give each set of numbers a more comprehensible name
  2. There are only a few fixed values in an enumeration, and there is no possibility of going out of range

export {} // Make sure there are no member conflicts with other examples

// Simulate enumeration with objects
// const PostStatus = {
// Draft: 0,
// Unpublished: 1,
// Published: 2
// }

// Standard enumeration of numbers
// enum PostStatus {
// Draft = 0,
// Unpublished = 1,
// Published = 2
// }

// Enumeration, enumeration value automatically increment based on the previous value
// enum PostStatus {
// Draft = 6,
// Unpublished, // => 7
// Published // => 8
// }

// String enumeration
// Set a value to the string if it is a string enumeration
// String enumerations are largely uncommon
// enum PostStatus {
// Draft = 'aaa',
// Unpublished = 'bbb',
// Published = 'ccc'
// }

// Constant enumeration does not invade the compiled result
const enum PostStatus {
  Draft,
  Unpublished,
  Published
}

const post = {
  title: 'Hello TypeScript'.content: 'TypeScript is a typed superset of JavaScript.'.status: PostStatus.Draft // 1 // 0
}

// Enumerations can be accessed through indexers
// PostStatus[0] // => Draft 
Copy the code

Function Types

Input and output type restrictions

Export {} // make sure there are no member conflicts with other examples // The function type annotation is string // If you want to select any number of arguments you can use the es6 operator... rest: number[] function func1 (a: number, b: number = 10, ... rest: number[]): string { return 'func1' } func1(100, 200) func1(100) func1(100, 200, 300) / / function expression of type restrictions -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- const func2: (a: number, b: number) => string = function (a: number, b: number): string { return 'func2' }Copy the code

Any Types

It belongs to the weak type category

Export {} // make sure there are no member conflicts with other examples // Accept any type arguments that are of dynamic type any) { return JSON.stringify(value) } stringify('string') stringify(100) stringify(true) let foo: Any = 'string' foo = 100 foo.bar() // The any type is unsafeCopy the code

Type Inference

Let age = 18 // number // age = 'string' let foo foo = 100 foo = 'string'Copy the code

Type assertion Type-assertion

export {} // Make sure there are no member conflicts with other examples

// Assume that the NUMS comes from an explicit interface
const nums = [110.120.119.112]

const res = nums.find(i= > i > 0)

// const square = res * res

// This is recommended
const num1 = res as number // Tell the type is number

const num2 = <number>res // It cannot be used under JSX
Copy the code

Interface Interfaces

  • A specification, convention, or contract
Export {} // make sure there are no member conflicts with other examples // Define an interface Post {title: string // Set type to string content: } function printPost (post: Post) { console.log(post.title) console.log(post.content) } printPost({ title: 'Hello TypeScript', content: 'A javascript superset' })Copy the code

Interface supplement

// Optional member, read-only member, dynamic member

export {} // Make sure there are no member conflicts with other examples

// -------------------------------------------

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

const hello: Post = {
  title: 'Hello TypeScript'.content: 'A javascript superset'.summary: 'A javascript'
}

// hello.summary = 'other'

// Dynamic member ----------------------------------

interface Cache {
  [prop: string] :string
}

const cache: Cache = {}

cache.foo = 'value1'
cache.bar = 'value2'
Copy the code

Class – basic

An abstract member that describes a class of concrete objects

  1. Before ES6, function + prototype simulated implementation classes
  2. ES6 began to have specialized classes in JavaScript
  3. TypeScript enhances class syntax

The basic use


export {} // Make sure there are no member conflicts with other examples

class Person {
  // An error is reported if the string type is not declared
  name: string // = 'init name'
  // An error is reported if the number type is not specified

  age: number
  
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
  }

  sayHi (msg: string) :void {
    console.log(`I am The ${this.name}.${msg}`)}}Copy the code

Access modifier

  1. Private Private property that can only be accessed internally with this
  2. Public Public Public member
  3. Protected cannot be accessed externally

Protected is accessible in subclasses using this

export {} // Make sure there are no member conflicts with other examples

class Person {
  // public represents the public member
  public name: string // = 'init name'
  Private attributes can only be accessed inside the class
  private age: number
  // protected Cannot be accessed externally but can be inherited
  protected gender: boolean
  
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    // Initialize gender
    this.gender = true
  }

  sayHi (msg: string) :void {
    console.log(`I am The ${this.name}.${msg}`)
    console.log(this.age)
  }
}
// Extend Student to Person
class Student extends Person {
  private constructor (name: string, age: number) {
    super(name, age)
    console.log(this.gender)
  }

  static create (name: string.age: number) {
    return new Student(name, age)
  }
}

const tom = new Person('tom'.18)
console.log(tom.name)
// console.log(tom.age)
// console.log(tom.gender)

const jack = Student.create('jack'.18)
Copy the code

Read-only property

  • Read-only attributes cannot be modified
export {} // Make sure there are no member conflicts with other examples

class Person {
  public name: string // = 'init name'
  private age: number
  // Read-only member
  protected readonly gender: boolean
  
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }

  sayHi (msg: string) :void {
    console.log(`I am The ${this.name}.${msg}`)
    console.log(this.age)
  }
}

const tom = new Person('tom'.18)
console.log(tom.name)
// Read-only members cannot be modified
// tom.gender = false
Copy the code

Classes and interfaces

export {} // Make sure there are no member conflicts with other examples
// Define a human interface
interface Eat {
  eat (food: string) :void
}
// Define an animal interface
interface Run {
  run (distance: number) :void
}
/ / class
class Person implements Eat.Run {
  eat (food: string) :void {
    console.log('Eat gracefully:${food}`)
  }

  run (distance: number) {
    console.log('Walking upright:${distance}`)}}/ / animal
class Animal implements Eat.Run {
  eat (food: string) :void {
    console.log('Oink oink eat:${food}`)
  }

  run (distance: number) {
    console.log(Crawl ` :${distance}`)}}Copy the code

An abstract class

  • Abstract classes use the keyword abstract
/ / abstract classes
// Abstract classes are recommended for large classes

export {} // Make sure there are no member conflicts with other examples
// abstract defines that abstract classes can only be inherited
abstract class Animal {
  eat (food: string) :void {
    console.log('Oink oink eat:${food}`)}abstract run (distance: number) :void
}
// Inherit Dog from Animal
class Dog extends Animal {
  run(distance: number) :void {
    console.log('Crawl on all fours', distance)
  }

}

const d = new Dog()
d.eat('Well, Sima.')
d.run(100)
Copy the code

Generic Generics

  • This refers to declaring without specifying its type and then specifying and passing its type when called

export {} // Make sure there are no member conflicts with other examples
// Create an array of the specified length
function createNumberArray (length: number, value: number) :number[] {
  const arr = Array<number>(length).fill(value)
  return arr
}

function createStringArray (length: number, value: string) :string[] {
  const arr = Array<string>(length).fill(value)
  return arr
}
// Generic parameters are usually named 
      
function createArray<T> (length: number, value: T) :T[] {
  const arr = Array<T>(length).fill(value)
  return arr
}

// const res = createNumberArray(3, 100)
// res => [100, 100, 100]
// Call this function
const res = createArray<string> (3.'foo')
Copy the code

Type Declaration Type Declaration

  • To be compatible with ordinary JS modules
/ / 1
import { camelCase } from 'lodash'

declare function camelCase (input: string) :string
const res = camelCase('hello typed'// The function is not prompted here, so it needs to be declared as above //2import { camelCase } from 'lodash' / / introduce lodash
import qs from 'query-string' // Parse the url's query string
qs.parse('? key=value&key2=value2')
// declare function camelCase (input: string): string
const res = camelCase('hello typed')

Copy the code