ts basic course

ts basic course (2)

type inference

If no type is specified explicitly, ts infers a type according to the rules of type inference

1. ts is more strict

Although TS is a js superset, it doesn't mean that all the uses of js can be copied. js can assign values to variables across types, but ts can't.

//In this way, ts will report an error. js is OK
let str="lengyuexin";
str=1024

2. ts inference results

ts is derived according to the type of the first variable assignment. In fact, the above code and the lower code are equivalent

//This string type is the result of ts's derivation based on the type of the first variable assignment
let str:string="lengyuexin";
str=1024

3. Define but not assign

If there is no value assigned when defining a variable, it will be inferred as any type regardless of whether there is value assigned later, and will not be checked at all

//It's not a good habit. It's like a runaway wild horse
//When you try to weaken the advantage of ts static type checking, it means that you still rely too much on js writing
let str;
str="lengyuexin"
str=1024;
str=[]
str=false;
str={}

Joint type

Union type indicates that the value can be one of several types. Different types are separated by the pipe character|, which is a bit like or.

1. Use example

let age:string|number;
age=18;//ok
age="18"//ok
age=false//error, not allowed for non union type subtypes

2. Access properties and methods of union type

It's a bit like intersection, only shared properties and methods can be accessed

//In this way, the code will report an error. The number type has no length attribute
function getLength(something: string | number): number {
    return something.length;
}
//But that's OK. Both strings and arrays have the length property
function getLength(something: string | number[]): number {
    return something.length;
}

//You can also access public methods like this
function getStr(something: string | number[]): string {
    return something.toString();
}

3. Type inference of joint type

The rules of type inference still apply to joint types

let age: string | number;
age = '20';
console.log(age.length); // normal operation
age = 20;// For the first assignment, age has been treated as string by ts
console.log(age.length); // Property 'length' does not exist on type 'number'.

Type Asserts

Type assertion can be used to manually specify the type of a value. There are two ways to use assertions in ts:

  1. < type > value
  2. The value as type must be used in TSX (ts version of react JSX) syntax

1. Assertions in JS

Console.assert (expression, message). If the expression is false, the message will be printed on the console

console.assert(true,"hello")//Normal operation, no output
console.assert(false,"hello")//VM2587:1 Assertion failed: hello

2. Assertion in TS

When a variable of a union type has not been determined, it can only access the properties or methods shared by the union subtype. Assertions can break this limitation

//It's a mistake
function getLength(something: string | number): number {
    if (something.length) {
        return something.length;
    } else {
        return something.toString().length;
    }
}

//ok with assertions

function getLength(something: string | number): number {
  if ((<string>something).length) {
      return (<string>something).length;
  } else {
      return something.toString().length;
  }
}

//Type assertion is not a type conversion. It is not allowed to assert a type that does not exist in a union type
// Error will be reported. boolean is not of union type string | number
function toBoolean(something: string | number): boolean {
    return <boolean>something;
}

Built-in object

The ts core library definition file defines the types needed by all browser environments. It has built-in type judgment and needs to install @ types/node for NodeJS

1. esma

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]/;
//...

2. bom/dom

Document, HTMLElement, Event, NodeList, etc.

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

3. Built in type check

//Error e is inferred as MouseEvent, but MouseEvent has no targetCurrent property
document.addEventListener('click', function(e) {
    console.log(e.targetCurrent);
});

Class and interface

In the last article, we used an interface to contract object types. In fact, an interface can also be used to abstract a behavior of a class. As for the class, it can be used to implement the specific specification of an interface, that is, the implementation class of an interface. Class can inherit (single inheritance), interface can also inherit (multi inheritance). The idea of object-oriented is more obvious in ts.

1. Class implementation interface

An interface can be an abstraction of a behavior of a class, and a class can implement multiple interfaces. Animals are regarded as a class and mammals as a subclass of animals. Both cats and dogs belong to mammals and both have the behavior of barking. This behavior can be abstracted as an interface.

//Define animal class if there is instance property, constructor is required
class Animal {
  color: string;
  constructor(color: string) {
    this.color = color;
  }
  //You can also declare instance methods
  yell(str:string):string{
    return str
  }
}


//*******************//

// The following example is based on the most primitive class Animal {}


//The act of calling is abstracted into an interface
interface AnimalYell{
    yell():void
}


//Defining animal classes
class Animal {
}


// Define the Mammal class, inherit the Animal class, and implement the AnimalYell interface

class Mammal extends Animal implements AnimalYell {
    yell() {
        console.log('Animals make calls');
    }
}

//Dog,Cat class inherits the parent class Mammal, overriding the yell method
// Here, you can also directly let dog and cat implement the AnimalYell interface
//The reason for inheritance is to reuse the features (properties and methods) of the parent class Mammal to a greater extent

class Dog extends Mammal {
    yell(){
         console.log('Wang Wang...');
    }
}

class Cat extends Mammal {
    yell(){
         console.log('Meow meow...');
    }
}



// A class can implement multiple interfaces
interface AnimalWalk{
    walk():void
}

//Snake implements two interfaces of animalwalk and animalyell\
//To implement an interface, you need to implement the methods in each interface
//If the following code is missing the implementation of yell or walk, an error will be reported
class Snake implements AnimalWalk,AnimalYell{
    yell(){
        console.log("hissing...")
    }

    walk(){
        console.log("Crawl...")
    }
}

new Mammal().yell()//Animals make calls
new Dog().yell()//Wang Wang...
new Cat().yell()//Meow meow...
new Snake().yell()//Hiss...
new Snake().walk()//Crawl...

2. Interface inheritance interface

Class can inherit, interface can also. In fact, interfaces in ts can also inherit classes, which is not allowed in other object-oriented languages (such as java).

//Abstract the function of mobile phone into an interface
interface BasePhoneFunction {
  call(): string; //Phone
  send(message: string): string[]; //Group SMS
}

// In addition to the basic functions, there are other functions
interface PhoneFunction extends BasePhoneFunction {
  game(): void; //Play games
  listen(): void; //Phonology
  watchTV(...tvName:string[]): void; //Watch TV
  note(): string[]; //Note
}

class Phone implements PhoneFunction {
  call() {
    return "hi, tom,when are we going to coding?";
  }

  send(message: string) {
    console.log(message);
    return ["tom", "jack", "july"];
  }

  game(){
    console.log("Play games")
  }
  listen(){
    console.log("Listen to the music")
  }
  //Note the rest parameter usage here. The parameter name does not have to be the same as the parameter name defined by the interface tvName
  watchTV(...args:string[]){
    console.log(`see${args.toString()} `)
  }

  note(...args:string[]){
    return [...args]
  }

}


const p=new Phone()
console.log(p.call())//hi, tom,when are we going to coding?
p.send("happy new year") //happy new year
console.log(p.send("happy new year"))// Happy new year ["tom", "jack", "july"]
p.game()//Play games
p.listen()//Listen to the music
p.watchTV("Nirvana in Fire","Will night")//Look at the langyabang, it's night
console.log(p.note("Having dinner","Sleep","Doudou"))//['eat', 'sleep', 'beat beans']

3. Interface inheritance class

It seems a little strange. How can an interface inherit a class? After all, ts has its particularity, just like js object does not support reverse mapping, but ts enumeration is object in nature, which can support reverse mapping (number based enumeration)

//Note that this method cannot be written without a constructor
class Person {
  eat: string;
  drink: string;
  constructor(eat:string,drink:string){
    this.eat=eat
    this.drink=drink
  }
}

//The interface PersonAction inherits the class Person, and the code runs normally
//What's the use of interface PersonAction? Define object
interface PersonAction extends Person {
  play: string;
}

const p: PersonAction={
  eat:"Boiled Fish with Pickled Cabbage and Chili",
  drink:"cola",
  play:"coding"
}

3.1 nature of interface inheritance class

In fact, an interface can inherit a class because the class in ts is special. It is not only a class for instantiation, but also a type specification

class Person {
  eat: string;
  drink: string;
  constructor(eat:string,drink:string){
    this.eat=eat
    this.drink=drink
  }
}

//This is the most common use
new Person("Boiled Fish with Pickled Cabbage and Chili","cola")

//You can also define objects as a type
const p:Person={
    eat:"Boiled Fish with Pickled Cabbage and Chili",
    drink:"cola"
}

The interface used to define objects before and can be used now, which shows that there are common features between the classes and interfaces in ts. Back to the beginning, the interface inherits classes to find out

class Person {
  eat: string;
  drink: string;
  constructor(eat:string,drink:string){
    this.eat=eat
    this.drink=drink
  }
}

//In fact, this kind of writing is equivalent to the following
interface PersonAction extends Person {
  play: string;
}


//=>Step1, pay attention to the similarities and differences between BasePerson and Person
interface BasePerson {
     eat: string;
     drink: string;
}
//=>step2
interface PersonAction extends BasePerson {
  play: string;
}

//This is still OK. The person class is actually disassembled into an interface
 const p:PersonAction={
  eat:"Boiled Fish with Pickled Cabbage and Chili",
  drink:"cola",
  play:"coding"
}


3.2 same and different

After the above exploration, we get the result: the essence of ts interface inheritance class is interface inheritance interface. But what's the difference between the base person class and the original person class? Take another example.

 class Person {
  //Instance attribute
  eat: string;
  drink: string;
  constructor(eat:string,drink:string){
    this.eat=eat
    this.drink=drink
  }
  //Example method
  log():void{
      console.log("log...")
  }

  //Static attribute
  static age:number=18;
  //Static method
  static log():void{
    console.log("static log...")
  }
}

console.log(Person.age)//18
Person.log()//static log...


// Changes when the class is inherited by the interface

interface BasePerson {
  eat: string
  drink: string
  log():void
}

  • There is no constructor. In fact, it's normal. It's just to define the type specification. It's not an instantiation. What do you want a constructor for?
  • Only instance properties and methods will be preserved, and static properties or methods will not be inherited

Access modifier

There are four kinds of access modifiers in java (public / protected / default / private), and three kinds of access modifiers in TS (public/protected/private)

1. public

Public has the highest permission. The default is public. You can freely access the members defined in the program

// Default writing
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

// Equivalent to this writing
class Person {
 public name: string;
 public constructor(name: string) {
    this.name = name;
  }
}

console.log(new Person("tom").name)//tom

2. private

class Person {
 private name: string;
 private constructor(name: string) {
    this.name = name;
  }
}

console.log(new Person("tom").name)//Error reported, no external access

3. protected

class Person {
  protected name: string;
  protected constructor(name: string) {
    this.name = name;
  }
}

class Student extends Person {
  constructor(name: string) {
    super(name); //Call parent constructor
  }

  getName(): string {
    //Student is a subclass of Person, so you can get the protected modified name attribute
    return this.name;
  }
}

console.log(new Student("tom").getName()); //tom

Reference link

  • Nugge ts volume, https://juejin.im/book/5da08714518825520e6bb810
  • ts Chinese manual, https://zhongsp.gitbooks.io/typescript-handbook
  • TS getting started, https://ts.xcatliu.com
455 original articles published, 830 praised, 230000 visitors+
His message board follow

Tags: Attribute Java React Mobile

Posted on Fri, 06 Mar 2020 02:21:02 -0800 by gszauer