Static versus dynamic typing

In dynamic language JS, variables have no type. And the values that are stored there are typed

let foo = 100
foo = 'Joe' // foo, which becomes a string
Copy the code
  • Type safety: strong type, weak type (whether implicit conversions are allowed: ‘100’ -50, which is actually computable)
  • Type checking: static type, dynamic type (whether variable types are allowed to change)

Basic data types

// Raw data type

const a: string = 'foobar'

const b: number = 100 // NaN Infinity

const c: boolean = true // false

// Under strictNullChecks,
String, number, and Boolean can all be null
// const d: string = null
// const d: number = null
// const d: boolean = null

const e: void = undefined

const f: null = null

const g: undefined = undefined

// Symbol is a member of the ES2015 standard,
// To use it, you must ensure that the corresponding ES2015 library reference is available
The lib option in tsconfig.json must contain ES2015
const h: symbol = Symbol(a)// Promise

// const error: string = 100
Copy the code

scope

  • Members in the default file are treated as global members
  • Conflicts occur when multiple files have the same member
// const a = 123

// Solution 1: IIFE provides independent scope
    (function () {
      const a = 123}) ()// Solution 2: Use export on the current file, that is, turn the current file into a module
// Modules have separate scopes
    const a = 123
    export {}
Copy the code

The Object type

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

The object type refers to any type other than the original type
const foo: object = function () {} / / / / [] {}

// If you need to explicitly restrict object types, you should use the syntax for object literals of that type, or "interfaces"
const obj: { foo: number, bar: string } = { foo: 123.bar: 'string' }
Copy the code

An array type

// 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

Tuples

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

// const age = tuple[0]
// const name = tuple[1]

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

Enumeration (Enum)

// 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
// 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
}

// PostStatus[0] // => Draft
Copy the code

Function types

function func1 (a: number, b: number = 10. rest: number[]) :string {
  return 'func1'
}

func1(100.200)

func1(100)

func1(100.200.300)

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

const func2: (a: number, b: number) = > string = function (a: number, b: number) :string {
  return 'func2'
}
Copy the code

Any type (weak type)

  • The any type is unsafe
export {} // Make sure there are no member conflicts with other examples

function stringify (value: any) {
  return JSON.stringify(value)
}

stringify('string')

stringify(100)

stringify(true)

let foo: any = 'string'

foo = 100

foo.bar()
Copy the code

Implicit type inference

  • Although there is type inference, it is recommended to add explicit type annotations for each variable
export {} // Make sure there are no member conflicts with other examples

let age = 18 // number

// age = 'string'

let foo

foo = 100

foo = 'string'
Copy the code

Types of assertions

  • Two ways, but as is preferred
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

const num1 = res as number

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

interface

A structure in an object that specifies that it must have members. Sort of like the interface documentation for the front and back ends

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

interface Post {
  title: string
  content: string
}

function printPost (post: Post) {
  console.log(post.title)
  console.log(post.content)
}

printPost({
  title: 'Hello TypeScript'.content: 'A javascript superset'
})
Copy the code

Optional member, read-only member, dynamic member

? Is not necessary

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

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

interface Post {
  title: string
  content: string subtitle? : string readonly summary: string }const hello: Post = {
  title: 'Hello TypeScript'.content: 'A javascript superset'.summary: 'A javascript'
}

// hello.summary = 'other'

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

interface Cache {
  [prop: string]: string
}

const cache: Cache = {}

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

Class (Class)

class Person {
  name: string // = 'init name'
  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

Class access modifier

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

class Person {
  public name: string // = 'init name'
  private age: number
  protected 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)
  }
}

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

Class read-only property

Public (default), private, protected, Readonly

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)
// tom.gender = false
Copy the code

Classes and interfaces

interface Eat {
  eat (food: string): void
}

interface Run {
  run (distance: number): void
}

class Person implements Eat.Run {
  eat (food: string): void {
    console.log('Eat gracefully:${food}`)
  }

  run (distance: number) {
    console.log('Walking upright:${distance}`)}}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

Smoke like class

  • Does not include concrete implementations, such as large classes
  • It can only be inherited, it can only be new
abstract class Animal {
  eat (food: string): void {
    console.log('Oink oink eat:${food}`)
  }

  abstract run (distance: number): void
}

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

The generic

When defining functions and interfaces, you do not specify specific types, and so on

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
}

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]

const res = createArray<string>(3.'foo')
Copy the code

Type declaration

The declaration corresponding to declare when used

import { camelCase } from 'lodash'
import qs from 'query-string'

qs.parse('? key=value&key2=value2')

// declare function camelCase (input: string): string

const res = camelCase('hello typed')
Copy the code