This is the 19th day of my participation in the August More Text Challenge

In order to share this article, I did a lot of work, so without my consent, please do not reprint, thank you!

Reading Tip: Explain and illustrate the distinction between class inheritance (extends) and implementation (Implement) in Typescript.

Most people think of Typescript as a superset of JavaScript that can be compiled into JavaScript. Typescript has the same capabilities as JavaScript, and you might think that Typescript is eventually compiled into JavaScript, and Typescript is growing in stature as a superset of JavaScript, One of the superlates of the more successful JavaScript, being able to sit in the same league table as the JavaScript it modifies, shows TypeScript to be something special.

In object-oriented programming, the most core is the concept of class, in ES2015, javascript has introduced the class keyword. But today we’ll take a look at how typescript complements JavaScript classes.

TypeScript provides full support for the class keyword introduced in ES2015. Like other JavaScript language features, TypeScript adds type annotations and other syntax that allow you to express relationships between classes and other types.

Define the class

A class is a closed organization of data structures and behaviors that can manipulate and access the data. It also provides methods for users to access and manipulate data.

Define a class

Let’s define a class that doesn’t contain anything. While some basic aspects of creating classes in TypeScript are covered, the syntax is mostly the same as when creating classes in JavaScript. So this article focuses on some of the differences between TypeScript and JavaScript.

class Tut{}
Copy the code

Attributes of a class

Inside a class you can declare properties and specify the type. The default property is public, which is a read/write property. If no modifier is given, the default property modifier is public.

// class Tut{}
class Tut{
    title:string;
    lesson:number;
}

const machine_learning_tut = new Tut();
machine_learning_tut.title = "machine leaerning tut";
machine_learning_tut.lesson = 12;

console.log(machine_learning_tut) //Tut { title: 'machine leaerning tut', lesson: 12 }

Copy the code

Specifying a type for an attribute is optional when it is declared. If no type is specified, the attribute type is any

class Tut{
    title = "";
    lesson = 0;
}

const machine_learning_tut = new Tut();
machine_learning_tut.title = "machine leaerning tut";
//error TS2322: Type 'string' is not assignable to type 'number'.
machine_learning_tut.lesson = "12";
Copy the code

The compiler will infer the property type from the initial value of the property. If the property is subsequently assigned a value other than the initialization value, the compilation will fail.

If specified at compile time strictPropertyInitialization to true this need in the constructor initializes the variable initial value is given.

{
    "compilerOptions": {..."strictNullChecks":true."strictPropertyInitialization":true,}}Copy the code
class Greeter{
    name:string
}
Copy the code

Because “strictPropertyInitialization” : true and no Greeter defined for the name attribute is given initial value will be thrown at compile time error information below.


Property 'name' has no initializer and is not definitely assigned in the constructor.
Copy the code

Please note that because “strictPropertyInitialization” : true the field need to be initialized in the constructor itself. TypeScript doesn’t analyze methods you call from constructors to detect initialization, because subclass classes may overwrite these methods and fail to initialize members.

If you intend to assign attributes outside the constructor, use the definite Assignment Assertion operator! .

class Greeter{ name! :string
}
Copy the code
class Employee{
    name:string
    constructor(name:string.public age:number){
        this.name = name; }}const mike = new Employee("mike".28)
console.log(mike.age)
Copy the code

Private property

class VideoTut extends Tut{
    private title:string
    constructor(title:string){
        //'super' must be called before accessing 'this' in the constructor of a derived class.ts(17009)
        // console.log(this.category)
        super(a)this.title = title
    }
}

const videoTut = new VideoTut("machine learning");
// Property 'title' is private and only accessible within class 'VideoTut'
console.log(videoTut.title)
Copy the code

When you modify the title with the private modifier, the property becomes private and cannot be accessed by outsiders. When attempting access, a Property ‘title’ is private and only accessible within class ‘VideoTut’ error is thrown.

Read-only properties (readonly)

If a class property is preceded by a readonly modifier, the value of the property can only be changed in the class constructor.

class Employee{
    readonly position:string = "employee"name! :string;constructor(name:string,otherPosition? :string){
        if(otherPosition ! = =undefined) {this.position = otherPosition;
            this.name = name; }}intro(){
        //Cannot assign to 'name' because it is a read-only property.ts(2540)
        this.position = "overide name field value"}}const mike = new Employee("mike");
//Cannot assign to 'position' because it is a read-only property.ts(2540)
mike.position = "overide name field valu"
Copy the code

Constructors

Class constructors are very similar to functions. You can add parameters, default values, and overloads with type annotations.

class Tut{
    title:string;
    subTitle:string;

    constructor(title:string,subTitle:string){
        this.title = title;
        this.subTitle = subTitle
    }
}
Copy the code

Constructors overload, even though constructors are functions, so overloading a constructor is also overloading a composite function.

class Tut{
    public title:string;
    public subTitle:string;

    constructor();
    constructor(title:string);
    constructor(title:any,subTitle? :any);
    constructor(title? :string,subTitle? :string){
        this.title = title;
        this.subTitle = subTitle; }}Copy the code

There are only a few differences between constructor signature and function signature of a class.

  • Constructors cannot have type arguments — this is the declaration of the outer class, which we’ll cover later.
  • Constructors cannot have return type annotations; constructors return the instance type of the class.

Super call

class Tut {
    category:string ="programming"
}

class VideoTut extends Tut{
    constructor(){
        //'super' must be called before accessing 'this' in the constructor of a derived class.ts(17009)
        console.log(this.category)
        super()}}Copy the code

Here VideoTut inherits

Methods of a class

Defining functions inside a class is called a method, and a method can be used in the same way as a function without obvious difference.

class VideoTut extends Tut{
    private title:string;
    constructor(title:string){
        //'super' must be called before accessing 'this' in the constructor of a derived class.ts(17009)
        // console.log(this.category)
        super(a);this.title = title;
    }

    description():string{
        return `title: The ${this.title}`}}const videoTut = new VideoTut("machine learning");
videoTut.description()//title: machine learning
Copy the code

getters/setters

We can set a property access setting by defining a set/get method. Through set/get, the outside world can access or modify some private properties of the class, but cannot modify properties that are readonly.

class Employee{
    private _name:string
    constructor(name:string.public age:number){
        this._name = name;
    }
    get name() {return this._name;
    }
    set name(newName:string) {this._name = newName; }}const mike = new Employee("mike".28)
console.log(mike.name)//mike
Copy the code

TypeScript has some special rules of inference for accessors.

  • If there is a GET but no set, the property is automatically readonly if the value was specified in the definitionreadonlyonlysetmethods
  • If not specifiedsetterParameter type, will be fromgetterIs inferred from the return type of
  • The getter and setter must have the same member visibility

Inheritance and implementation

Inheritance (extends)

In most class-based object-oriented languages, inheritance is a mechanism in which one object acquires all of the attributes and behavior of the parent object. Inheritance allows programmers to create classes that build on top of existing classes

Implementation (implements)

You can implement a class using the implements statement, and the compilation process checks whether the class Developer that implements the CanDoSomethingInterface meets the implementation interface requirements. If the interface definition is not implemented, the compilation process prompts an error.

interface CanDoSomethingInterface{
    canDoSomething():void;
}

class Employee{
    private _name:string
    constructor(name:string.public age:number){
        this._name = name;
    }
    get name() {return this._name;
    }
    set name(newName:string) {this._name = newName; }}class Developer extends Employee implements CanDoSomethingInterface{

    canDoSomething():void{
        console.log(`The ${this.name} can write some code`)}}const mike = new Developer("mike".28)
// mike.name = "tony"
// console.log(mike.name)
mike.canDoSomething() //mike can write some code
Copy the code

By inheritance, a subclass owns all the attributes and methods of its parent class, can override (implement) the parent class methods, and can extend some attributes and methods from the parent class.

Multiple interfaces can be implemented

interface Sendable{
    send():void;
}

interface Receivable{
    receive():void;
}

class EMail implements Sendable.Receivable{
    send():void{

    }
    receive():void{}}Copy the code

There are multiple interfaces to a class, and above EMail implements the Sendable and Receivable interfaces. It seems that interface implementation and class inheritance are very similar, but they are two different things. First of all, interfaces are more abstract. Many languages use contracts for interfaces, which can also be understood as types, which are type constraints based on behavior or data, or contracts, which can be used to connect different things.

It’s important to understand that the implements clause simply checks whether a class can be considered an interface type, that is, whether the class implements methods of the interface. But it does not change the type of the class or its methods. A common source of error is thinking that the implements clause changes the type of a class.

In this case, we might expect the type of S to be affected by the name: string argument to check. It doesn’t — the implementation clause doesn’t change the way the body of a class is checked or its type inferred.

Similarly, implementing an interface with an optional property does not create that property.

Override a method

Subclasses can also override a field or attribute of the base class. You can use the super. syntax to call the methods of the base class. TypeScript requires that a subclass always be a subtype of its base class.

class Employee{
  intro(){
    console.log("I am employee"); }}class Developer extends Employee{
  intro(){
    super.intro();
    console.log("I'm a developer")}}const mike = new Developer()
mike.intro()
Copy the code

A subclass needs to search its base class contract, so it can be used as a base class type.

    class Employee{
        intro(){
            console.log("I am employee"); }}class Developer extends Employee{
        intro(name? :string){
            if(name == undefined) {super.intro();
            }else{
                console.log(`I'm a developer and my name is ${name}`)}}}const mike:Developer = new Developer()
    mike.intro("mike")
Copy the code

An error is thrown if a subclass implements an intro method without following the superclass definition.

intro(name:string)
Copy the code
Property 'intro' in type 'Developer' is not assignable to the same property in base type 'Employee'.
  Type '(name: string) => void' is not assignable to type '() => void'.ts(2416)
Copy the code

Initialization sequence

    class Tut{
        level = "begin"
        constructor(){
            console.log(`level: The ${this.level}`)}}class MachineLearningTut extends Tut{
        level = "advance" 
    }

    const tut = new MachineLearningTut()
    // level: begin
Copy the code

The order in which classes are initialized is defined by JavaScript.

  • Initializes the fields of the base class
  • Execute the base class constructor
  • Initializes the field of the subclass
  • Executes the subclass constructor

This means that the base class constructor sees the base class name value in its constructor instead of the subclass name, because the subclass’s field initialization has not yet been run.