• Chinese version of TypeScript Tutorial – Project introduction
  • TypeScript Tutorial Chinese version – Section 0. preface
  • TypeScript Tutorial Chinese version – Section 1. An introduction to
  • TypeScript Tutorial Chinese version – Section 2. Basic types of
  • TypeScript Tutorial Chinese version – Section 3. Control flow statement
  • TypeScript Tutorial Chinese – Section 4. function
  • TypeScript Tutorial Chinese version – Section 5. class
  • TypeScript Tutorial Chinese version – Section 6. interface
  • TypeScript Tutorial Chinese version – Section 7. High-level types
  • TypeScript Tutorial Chinese version – Section 8. The generic
  • TypeScript Tutorial Chinese version – Section 9. The module
  • Chinese version of TypeScript Tutorial – Section 10.node.js

Section 5. Class

class

The original address

In this tutorial, you’ll learn about classes in TypeScript.

Introduction to classes in TypeScript

Unlike other programming languages, such as Java and C#, JavaScript has the concept of a class, and in ES5 you can create a “class” through constructors and stereotype inheritance. For example, to create a Person class with SSN, firstName, and lastName attributes, you could use the following constructor:

function Person(ssn, firstName, lastName) {
  this.ssn = ssn;
  this.firstName = firstName;
  this.lastName = lastName;
}
Copy the code

Next, define a prototype method to get the full name of the person by concatenating the values of the firstName and lastName attributes:

Person.prototype.getFullName = function () {
  return `The ${this.firstName} The ${this.lastName}`;
};
Copy the code

You can then create a new object from the Person “class” :

let person = new Person('171-28-0926'.'John'.'Doe');
console.log(person.getFullName());
Copy the code

It prints the following message on the console:

John Doe
Copy the code

ES6 allows you to define a class that is the syntactic sugar for creating the corresponding constructor and stereotype inheritance:

class Person {
  ssn;
  firstName;
  lastName;

  constructor(ssn, firstName, lastName) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName; }}Copy the code

In the syntax of the class above, the constructor is already explicitly defined in the class. Next add the getFullName() method:

class Person {
  ssn;
  firstName;
  lastName;

  constructor(ssn, firstName, lastName) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    return `The ${this.firstName} The ${this.lastName}`; }}Copy the code

The object created using the Person class is the same as the object created using the Person constructor:

let person = new Person('171-28-0926'.'John'.'Doe');
console.log(person.getFullName());
Copy the code

Classes in TypeScript add type annotations to their properties and methods. Here’s how to use the Person class in TypeScript:

class Person {
  ssn: string;
  firstName: string;
  lastName: string;

  constructor(ssn: string, firstName: string, lastName: string) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`; }}Copy the code

When you add type annotations to class properties, constructors, and methods, the TypeScript compiler does type checking. For example, you cannot initialize SSN as a value of type number. The following code will throw an error:

let person = new Person(171280926.'John'.'Doe');
Copy the code

summary

  • Used in TypeScriptclassKeyword definition class;
  • TypeScript adds type annotations to the syntax of ES6 classes to make them more robust to use.

Access modifier

The original address

In this tutorial, you’ll learn about access modifiers in TypeScript.

Access modifiers change the visibility of properties and methods in a class. TypeScript provides three access modifiers:

  • private
  • protected
  • public

Note that TypeScript controls the visibility of properties and methods at compile time, not at run time.

Private modifiers

Private modifiers restrict properties and methods to being visible only in the current class. This means that when you add a private modifier to a method or property, it can only be accessed in the current class. Accessing private properties and methods outside the current class will raise an error at compile time.

The following example shows how to add the private modifier to the SNN, firstName, and lastName attributes of the Person class:

class Person {
  private ssn: string;
  private firstName: string;
  private lastName: string;
  // ...
}
Copy the code

With the private modifier, you can access the SSN attribute in a constructor or Person class method, such as:

class Person {
  private ssn: string;
  private firstName: string;
  private lastName: string;

  constructor(ssn: string, firstName: string, lastName: string) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`; }}Copy the code

Try accessing the SSN attribute outside of the Person class:

let person = new Person('the 153-07-31 30'.'John'.'Doe');
console.log(person.ssn); // compile error
Copy the code

The public modifier

The public modifier allows class properties and methods to be accessed from anywhere. If no modifier is specified for the properties and methods, the default is the public modifier.

Add the public modifier to the getFullName() method in the Person class as shown below:

class Person {
  // ...
  public getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`;
  }
  // ...
}
Copy the code

It has the same effect as omitting the public keyword.

Protected modifier

The protected modifier allows the properties and methods of a class to be accessed within the current class or a subclass of the current class. When a class (subclass) inherits from another class (parent class), it is a subclass of the parent class. If you try to access protected properties from anywhere else, the TypeScript compiler will throw an error.

Add protected modifiers to methods and properties using the protected keyword, as follows:

class Person {
  protected ssn: string;
  // other code
}
Copy the code

The SSN attribute is now protected, accessible in the Person class and any subclasses that inherit the Person class, and you can learn more about inheritance from class inheritance.

The Person class declares two private and one protected properties, and the constructor initializes them with the three parameters it receives.

To make your code look simpler, TypeScript allows you to declare and initialize properties at the same time in constructors, like this:

class Person {
  constructor(
    protected ssn: string.private firstName: string.private lastName: string.) {
    this.ssn = ssn;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`; }}Copy the code

When you consider the visibility of properties and methods, it is best to give them the lowest visibility access modifier, the private modifier.

summary

  • TypeScript provides three access modifiers for properties and methods:private.protectedpublicThe modifier;
  • privateModifiers are accessible only in the current class;
  • protectedModifiers allow access in the current class and subclasses of the current class;
  • publicModifiers can be accessed anywhere.

Read-only property

The original address

In this tutorial, you’ll learn how to use TypeScript read-only access modifiers, which mark class properties as immutable.

TypeScript provides read-only access modifiers that allow you to mark class properties as immutable. You can only add read-only attributes to attributes in one of two places:

  • Where attributes are defined;
  • Constructor of the current class.

To mark an attribute as immutable, you need to use the readonly keyword. Here’s how to declare a read-only attribute in the Person class:

class Person {
  readonly birthDate: Date;

  constructor(birthDate: Date) {
    this.birthDate = birthDate; }}Copy the code

In this case, birthDate is a read-only property that is initialized in the constructor of the Person class. Try reassigning the birthDate attribute and throw an error message like the following:

let person = new Person(new Date(1990.12.25));
person.birthDate = new Date(1991.12.25); // Compile error
Copy the code

Like other access modifiers, you can declare and initialize read-only properties in the constructor, as follows:

class Person {
  constructor(readonly birthDate: Date) {
    this.birthDate = birthDate; }}Copy the code

Readonly vs const

Here are the differences between readonly and const:

readonly const
Used for Attributes of a class variable
Initialize the When a property is declared or in the current class constructor When you declare variables

summary

  • Use read-only access modifiers to mark class attributes as immutable;
  • Read-only access modifications must be initialized at the time the property is declared or in the current class constructor.

Getter / Setter

The original address

In this tutorial, you’ll learn how to use getters and setters in TypeScript.

An introduction to getter and setter methods in TypeScript

Here is a simple Person class with only three attributes: Age, firstName, and lastName.

class Person {
  public age: number;
  public firstName: string;
  public lastName: string;
}
Copy the code

To access the attributes of the Person class, do this:

let person = new Person();
person.age = 26;
Copy the code

Suppose you assign a value from user input to the age property:

person.age = inputAge;
Copy the code

The inputAge variable can be any number, and can be checked before assigning to be valid for age:

if (inputAge > 0 && inputAge < 200) {
  person.age = inputAge;
}
Copy the code

But using this check statement everywhere is redundant and tedious. To avoid double checking, you can use getter and setter methods, which control how class attributes are accessed. For each attribute:

  • getterMethod returns the value of the property,getterMethods are also known asaccessorMethods;
  • setterMethod updates the value of the property,setterMethods are also known asmutatorMethods.

Getter methods begin with the get keyword, while setter methods begin with the set keyword:

class Person {
  private _age: number;
  private _firstName: string;
  private _lastName: string;

  // We didn't write the constructor function in TypeScript
  constructor(age: number, firstName: string, lastName: string) {
    this._age = age;
    this._firstName = firstName;
    this._lastName = lastName;
  }

  public get age() {
    return this._age;
  }

  public set age(theAge: number) {
    if (theAge <= 0 || theAge >= 200) {
      throw new Error('The age is invalid');
    }
    this._age = theAge;
  }

  public getFullName(): string {
    return `The ${this._firstName} The ${this._lastName}`; }}Copy the code

Here’s how it works:

  • First, theage.firstNamelastNameProperty from the access modifierpublicChange toprivate;
  • Next, let’s putageProperty changed to_age;
  • The third,_ageAttribute to addgettersetterMethods,setterIn the user input age variable value assigned to_ageProperty, check if the variable value is valid.

Now, you can access the setter method of age as follows:

let person = new Person();
person.age = 10;
Copy the code

Notice that calling setter methods does not have parentheses in the method name, as regular method calls do. When you call Person. age, the setter method for age is called. If you set an invalid age value, the setter method throws an error message:

person.age = 0;
Copy the code

Error message:

Error: The age is invalid
Copy the code

When you access Person. age, the age getter is called:

console.log(person.age);
Copy the code

Here we add getter and setter methods to firstName and lastName attributes:

class Person {
  private _age: number;
  private _firstName: string;
  private _lastName: string;

  // We didn't write the constructor function in TypeScript
  constructor(age: number, firstName: string, lastName: string) {
    this._age = age;
    this._firstName = firstName;
    this._lastName = lastName;
  }

  public get age() {
    return this._age;
  }

  public set age(theAge: number) {
    if (theAge <= 0 || theAge >= 200) {
      throw new Error('The age is invalid');
    }
    this._age = theAge;
  }

  public get firstName() {
    return this._firstName;
  }

  public set firstName(theFirstName: string) {
    if(! theFirstName) {throw new Error('Invalid first name.');
    }
    this._firstName = theFirstName;
  }

  public get lastName() {
    return this._lastName;
  }

  public set lastName(theLastName: string) {
    if(! theLastName) {throw new Error('Invalid last name.');
    }
    this._lastName = theLastName;
  }

  public getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`; }}Copy the code

More getter/setter methods examples

As you can see from the code, it is very useful to use setter methods to validate data before assigning values to properties, and you can do other complex logic as well.

Here’s how to create getter and setter methods for fullName:

class Person {
  // ... other code
  public get fullName() {
    return `The ${this.firstName} The ${this.lastName}`;
  }

  public set fullName(name: string) {
    let parts = name.split(' ');
    if(parts.length ! =2) {
      throw new Error('Invalid name format: first last');
    }
    this.firstName = parts[0];
    this.lastName = parts[1]; }}Copy the code

Here’s how it works:

  • getterMethod returnsfirstNamelastNameConcatenated string;
  • setterMethod accepts a string asfullNameVariable, which has the following format: The first part of the string is assigned tofirstNameProperty, the second part of the string is assigned tolastNameProperties.

Now you can access the setter and getter properties of fullName just like a normal class property:

let person = new Person();
person.fullname = 'John Doe';

console.log(person.fullName);
Copy the code

summary

  • Use TypeScriptgetter / setterMethod to control how class attributes are accessed;
  • getter / setterMethods are also known asaccessor / mutatorMethods.

Class inheritance

The original address

In this tutorial, you’ll learn about the concept of inheritance in TypeScript and how to use it to override the functionality of other classes.

Introduction to inheritance in TypeScript

A class can have its properties and methods reused by other classes, which in TypeScript is called inheritance. Classes that inherit the properties and methods of other classes are called subclasses, and inherited classes are called parent classes. These names come from the way in nature that children inherit their parents’ genes. Inheritance lets you reuse the functionality of existing classes without having to rewrite them all over again.

JavaScript implements classes using archetypal inheritance rather than Java and C# class inheritance. The class syntax introduced in ES6 is the syntactic sugar of JavaScript archetypal inheritance, and TypeScript also supports it.

Suppose we have the following Person class:

class Person {
  constructor(private firstName: string.private lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  getFullName(): string {
    return `The ${this.firstName} The ${this.lastName}`;
  }
  describe(): string {
    return `This is The ${this.firstName} The ${this.lastName}. `; }}Copy the code

Use the extends keyword to extend other classes. For example, the following Employee class extends from the Person class:

class Employee extends Person {
  / /..
}
Copy the code

In this example, Employee is a subclass and Person is the parent class.

The constructor

Because the Person class has a constructor that initializes firstName and lastName attributes, you need to call the parent constructor in the Employee constructor to initialize these attributes. To call the parent class’s constructor in a subclass’s constructor, use the super() syntax:

class Employee extends Person {
  constructor(firstName: string, lastName: string.private jobTitle: string) {
    // call the constructor of the Person class:
    super(firstName, lastName);
    this.jobTitle = jobTitle; }}Copy the code

Here we create an instance of the Employee class:

let employee = new Employee('John'.'Doe'.'Front-end Developer');
Copy the code

Because the Employee class inherits the methods and attributes of the Person class, you can call the getFullName() and describe() methods on the Employee object, as follows:

let employee = new Employee('John'.'Doe'.'Web Developer');

console.log(employee.getFullName());
console.log(employee.describe());
Copy the code

Output:

John Doe
This is John Doe.
Copy the code

Method overloading

When you call the Employee.describe () method on the Employee object, the Describe () method of the Person class is executed, displaying This is John Doe information. If the Employee class wants to have its own describe() method, you can define the Describe () method in the Employee class, as follows:

class Employee extends Person {
  constructor(firstName: string, lastName: string.private jobTitle: string) {
    super(firstName, lastName);
    this.jobTitle = jobTitle;
  }

  describe(): string {
    return super.describe() + `I'm a The ${this.jobTitle}. `; }}Copy the code

In the describe () method, we use super. MethodInParentClass () syntax to invoke the describe of the parent () method. If you call the describe() method on an Employee object, the describe() method of the Employee class will be called:

let employee = new Employee('John'.'Doe'.'Web Developer');
console.log(employee.describe());
Copy the code

Output:

This is John Doe.I'm a Web Developer.
Copy the code

summary

  • useextendsKeywords allow one class to inherit from another;
  • Used in the constructor of a subclasssuperMethod calls the parent class’s constructor, used in a subclass’s methodsuper.methodInParentClass()The syntax calls the parent classmethodInParentClass()Methods.

Static properties and methods

The original address

In this tutorial, you’ll learn about static properties and methods in TypeScript.

Static attributes

Unlike instance properties, static properties are shared between all instances of a class. To declare static properties, use the static keyword, and to access static properties, use the classname.propertyName syntax, as follows:

class Employee {
  static headcount: number = 0;

  constructor(
    private firstName: string.private lastName: string.private jobTitle: string.){ Employee.headcount++; }}Copy the code

In this case, headCount is a static property with an initial value of 0, which is incremented by one each time a new instance is created. The following example creates two Employee instances that print the value of the headCount property and return the expected 2:

let john = new Employee('John'.'Doe'.'Front-end Developer');
let jane = new Employee('Jane'.'Doe'.'Back-end Developer');

console.log(Employee.headcount); / / 2
Copy the code

A static method

Static methods, like static properties, are shared between all instances of the class. To declare a static method, add the static keyword to the name of the method, as shown below:

class Employee {
  private static headcount: number = 0;

  constructor(
    private firstName: string.private lastName: string.private jobTitle: string.) {
    Employee.headcount++;
  }

  public static getHeadcount() {
    returnEmployee.headcount; }}Copy the code

In this example:

  • First of all,headcountStatic property access modifiers frompublicChange toprivate, so that its value cannot be changed outside the class unless a new one is createdEmployeeInstance;
  • Then, addgetHeadcount()Static method that returnsheadcountThe value of a static property.

You can use the syntax classname.staticmethod () to call a staticMethod, as follows:

let john = new Employee('John'.'Doe'.'Front-end Developer');
let jane = new Employee('Jane'.'Doe'.'Back-end Developer');

console.log(Employee.getHeadcount); / / 2
Copy the code

In fact, you’ll find that Math objects have lots of static properties and methods, such as static properties for PI and E, static methods for abs() and round(), etc.

summary

  • Static properties and methods are shared between all instances of a class;
  • To be added before a property or method namestaticKeyword that can be made a static property or a static method.

Abstract methods

The original address

In this tutorial, you’ll learn about abstract classes in TypeScript.

Introduction to abstract classes in TypeScript

Abstract classes are usually used to define the common behavior of derived classes to be extended, and unlike regular classes, abstract classes cannot be instantiated directly. To declare an abstract class, use the abstract keyword:

abstract class Employee {
  / /...
}
Copy the code

Typically, an abstract class contains one or more abstract methods. An abstract method contains no concrete implementation; it defines only the signature of the method, not the method body, whereas an abstract method must be implemented in a derived class.

Here is an abstract Employee class with the getSalary() abstract method:

abstract class Employee {
  constructor(private firstName: string.private lastName: string) {}
  abstract getSalary(): number;
  get fullName() :string {
    return `The ${this.firstName} The ${this.lastName}`;
  }
  compensationStatement(): string {
    return `The ${this.fullName} makes The ${this.getSalary()} a month.`; }}Copy the code

In the Employee class:

  • The constructor is declaredfirstNamelastNameProperties;
  • getSalary()A method is an abstract method, and a derived class implements concrete logic based on the employee’s type;
  • getFullName()compensationStatement()Methods have concrete implementations, notecompensationStatement()Method will callgetSalary()Methods.

Because Employee is an abstract class and cannot be used to create an instance, the following statement throws an error:

let employee = new Employee('John'.'Doe');
Copy the code

Error message:

error TS2511: Cannot create an instance of an abstract class.
Copy the code

The following FullTimeEmployee class inherits the Employee abstract class:

class FullTimeEmployee extends Employee {
  constructor(firstName: string, lastName: string.private salary: number) {
    super(firstName, lastName);
  }
  getSalary(): number {
    return this.salary; }}Copy the code

In the FullTimeEmployee class, the constructor defines the salary attribute. Because getSalary() is an abstract method of Employee, FullTimeEmployee needs to implement this method. In this case, the method does nothing and returns the value of the salary variable to represent the value of the salary.

The following Contractor class inherits the Employee abstract class:

class Contractor extends Employee {
  constructor(
    firstName: string,
    lastName: string.private rate: number.private hours: number.) {
    super(firstName, lastName);
  }
  getSalary(): number {
    return this.rate * this.hours; }}Copy the code

In the Contractor class, the constructor defines the rate and hours properties, and the getSalary() method multiplies the rate and hours to show the value of the reward.

The following example creates an instance of the FullTimeEmployee class and an instance of the Contractor class, and displays their compensation information on the console:

let john = new FullTimeEmployee('John'.'Doe'.12000);
let jane = new Contractor('Jane'.'Doe'.100.160);

console.log(john.compensationStatement());
console.log(jane.compensationStatement());
Copy the code

Output:

John Doe makes 12000 a month.
Jane Doe makes 16000 a month.
Copy the code

When you want to share code between classes that are related to each other, using abstract classes is a good way to do it.

summary

  • Abstract classes cannot be instantiated;
  • An abstract class has at least one abstract method;
  • When you use an abstract class, you need to inherit it and implement all the abstract methods in the class.