当前位置:网站首页>Typescript learning [5] type

Typescript learning [5] type

2022-06-09 04:46:00 Large American without sugar

stay JavaScript(ES5) Only functions and prototype chains can be used to inherit the implementation of simulation classes ( For abstracting business models 、 Organize data structures and create reusable components ), since ES6 introduce class The key word , It has just begun to support the use of Java A similar syntax defines a declaration class .

TypeScript As JavaScript Superset , Naturally, I support class All characteristics , And you can also modify the properties of the class 、 Methods, etc. for static type detection .

class

In real business , Any entity can be abstracted as a data structure similar to an object expressed by a class , And this data structure contains both attributes , It also includes methods , For example, we abstract a dog class below .

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

  bark() {
    
    console.log(' Wang ! Wang ! Wang !');
  }
}

const dog = new Dog('QQ');
dog.bark(); //  Wang ! Wang ! Wang !

First , We define a class Dog , It has a string Type of name attribute 、bark Method and a constructor function . then , We go through new Keyword creates a Dog Example , And assign the instance to the variable dog. Last , We invoke the defined in the class through an instance bark Method .

Inherit

stay TypeScript in , Use extends Keyword can easily define abstract patterns of class inheritance , As shown in the following code :

class Animal {
    
  type = 'Animal';
  say(name: string) {
    
    console.log(` I am a  ${
      name}`);
  }
}

class Dog extends Animal {
    
  bark() {
    
    console.log(' Wang ! Wang ! Wang !');
  }
}

const dog = new Dog();
dog.bark(); //  Wang ! Wang ! Wang !
dog.say('QQ'); //  I am a QQ
console.log(dog.type) // Animal

The above example shows the most basic inheritance usage of a class . For example, as defined in the code Dog Is a derived class , It is derived from the As previously defined Animal Base class , here Dog Instance inherits the base class Anima l Of Properties and methods . therefore , We can see examples dog Support bark、say、type Other properties and methods .

explain : Derived classes are often called subclasses , Base classes are also called superclasses ( Or the parent class ).

Careful you may have found , there Dog The base class is compared with the class in the first example , One constructor is missing . This is because if a derived class contains a constructor , It must be called in the constructor. super() Method , This is a TypeScript An important rule of enforcement .

The following example , Because first defined Dog There is no call to... In the class constructor super Method , So it suggests a ts(2377) Error of ; And then defined Dog Class constructors add super Method call , So you can use type detection .

class Animal {
    
  type = 'Animal';
  say(name: string) {
    
    console.log(` I am a  ${
      name}`);
  }
}

class Dog extends Animal {
    
  name: string;
  constructor(name: string) {
     // error TS2377: Constructors for derived classes must contain a 'super' call.
    this.name = name;
  }
  bark() {
    
    console.log('Woof! Woof!');
  }
}

// class Dog extends Animal {
    
// name: string;
// constructor(name: string) {
    
// super()
// this.name = name
// }
// bark() {
    
// console.log(' Wang ! Wang ! Wang !');
// }
// }

const dog = new Dog('QQ');
dog.bark();
dog.say('QQ');
console.log(dog.type)

there super() What's the function ? In fact, the super function Will call the constructor of the base class , As shown in the following code :

class Animal {
    
  weight: number;
  type = 'Animal';
  constructor(weight: number) {
    
    this.weight = weight;
  }
  say(name: string) {
    
    console.log(` I am a ${
      name}`);
  }
}

class Dog extends Animal {
    
  name: string;
  constructor(name: string) {
    
    super(); // error TS2554: Expected 1 arguments, but got 0.
    this.name = name
  }
  bark() {
    
    console.log(' Wang ! Wang ! Wang !');
  }
}

Put the mouse on Dog Class constructor calls super On the function , We can see a hint , Its type is the base class Animal Constructor for :constructor Animal(weight: number): Animal . And because Animal Class constructor requires that a numeric type of weight Parameters , The actual input parameter is null , So it suggests a ts(2554) Error of ; If we explicitly give super The function passes in a number Type value , for instance super(20), No more errors will be prompted .

public 、 Private and protected modifiers

Class properties and methods can be passed through extends Beyond being inherited , Accessibility can also be controlled by modifiers .

stay TypeScript I'm in support of 3 An access modifier , Namely publicprivateprotected.

  • public The decoration is in anyplace so 、 A public property or method ;

  • private Modification is Only in the same category so 、 A private property or method ;

  • protected Modification is Only in the class itself and its subclasses so 、 A protected property or method .

In the previous code , Example classes do not use visibility modifiers , By default , The default property or method of a class is public. If you want to make some attributes invisible , Then we can use private Set it up , As shown below :

class Someone {
    
  public firstName: string;
  private lastName: string = 'Jae';
  constructor(firstName: string) {
    
    this.firstName = firstName;
    this.lastName
  }
}

const person = new Someone('Wong');
console.log(person.firstName); // Wong
person.firstName = 'Jack';
console.log(person.firstName); // Jack
console.log(person.lastName); // error TS2341: Property 'lastName' is private and only accessible within class 'Someone'.

In the example above we can see ,Somone Class lastName Property is private , Only in Somone Class ; And the code defines firstName Property is public , It can be seen everywhere . therefore , We can both create Somone Class person Gets or sets the public firstName Properties of , You can also manipulate changes firstName Value .

however , about private Decorated private properties , It can only be seen inside the class . Like private properties lastName Only in Somone Class , If other places get lastName ,TypeScript Will prompt a ts(2341) Error of .

Be careful : TypeScript The private property of the class defined in represents only the private property of the static type detection level . If we force to ignore TypeScript Type check error , Translate and run JavaScript You can still get lastName attribute , This is because JavaScript Does not support real private attributes .

Next, let's look at protected properties and methods , As shown in the following code :

class Someone {
    
  public firstName: string;
  protected lastName: string = 'Jae';
  constructor(firstName: string) {
    
    this.firstName = firstName;
    this.lastName
  }
}

class Otherone extends Someone {
    
  constructor(firstName: string) {
    
    super(firstName);
  }
  public getMyLastName() {
    
    return this.lastName;
  }
}

const oth = new Otherone('Tony');
console.log(oth.getMyLastName()); // Jae
oth.lastName; // error TS2445: Property 'lastName' is protected and only accessible within class 'Someone' and its subclasses.

In the code , modify Someone Class lastName The attribute visible modifier is protected, Indicates that this attribute is in Someone Class and its subclasses . We can either in the parent class Someone Get from the constructor of lastName Property value , It can also be inherited from Someone Subclasses of Otherone Of getMyLastName Method to get lastName The value of the property .

We need to pay attention to : Although we cannot access through instances of derived classes protected The attributes and methods of decoration , But it can be accessed through the instance method of the derived class . For example, in the example, the getMyLastName Method to get the protected property lastName yes ok Of , And the first 22 Rows get protected attributes directly through instances lastName It prompts a ts(2445) Error of .

Read only modifier

In the previous example ,Someone class public Decorated attributes are both publicly visible , You can also change the value , If we don't want the properties of the class to be changed , You can use readonly The read-only modifier declares the properties of the class , As shown in the following code :

class Someone {
    
  public readonly firstName: string;
  protected lastName: string = 'Jae';
  constructor(firstName: string) {
    
    this.firstName = firstName;
  }
}

const person = new Someone('Tony');
person.firstName = 'Jack'; // error TS2540: Cannot assign to 'firstName' because it is a read-only property.

In the example, we expose the visible properties to firstName Read only modifier specified , If you change it again at this time firstName The value of the property ,TypeScript Will prompt a ts(2540) Error of . This is because the read-only attribute modifier ensures that the attribute can only be read , It can't be modified .

Be careful : If the read-only modifier and the visibility modifier appear at the same time , We need to write the read-only modifier after the visible modifier .

Accessors

In addition to the modifiers mentioned above , stay TypeScript You can also use gettersetter Intercept read and write access to class members .

Interception through access to class properties , We can implement some specific access control logic . Let's transform the previous example , As shown in the following code :

class Son {
    
  public firstName: string;
  protected lastName: string = 'Stark';
  constructor(firstName: string) {
    
    this.firstName = firstName;
  }
}

class GrandSon extends Son {
    
  constructor(firstName: string) {
    
    super(firstName);
  }
  get myLastName() {
    
    return this.lastName;
  }
  set myLastName(name: string) {
    
    if (this.firstName === 'Tony') {
    
      this.lastName = name;
    } else {
    
      console.error('Unable to change myLastName');
    }
  }
}

const grandSon = new GrandSon('Tony');
console.log(grandSon.myLastName); // Stark
grandSon.myLastName = 'Rogers';
console.log(grandSon.myLastName); // Rogers
const grandSon2 = new GrandSon('Tony1');
grandSon2.myLastName = 'Rogers'; // Unable to change myLastName

In the above code , Use myLastName Of gettersetter Rewriting the previous GrandSon Class method , stay getter What is actually returned in is lastName attribute . then , stay setter in , Limited only if lastName The property value is ‘Tony’ , Just put it into the reference name Assign to it , Otherwise, the printing error .

Static attribute

All the properties and methods of the class described above , Only Class when instantiated Will be initialized . actually , We can also define static properties and methods for classes .

Because these attributes exist on the special object class , Not on instances of classes , So we can access static properties directly through classes , As shown in the following code :

class MyArray {
    
  static displayName = 'MyArray';
  static isArray(obj: unknown) {
    
    return Object.prototype.toString.call(obj).slice(8, -1)
  }
}
console.log(MyArray.displayName);
console.log(MyArray.isArray([]));
console.log(MyArray.isArray({
    }));

adopt static Modifier , We give MyArray Class defines a static attribute displayName And static methods isArray. after , We do not need to instantiate MyArray You can directly access the static properties and methods on the class .

Features based on static attributes , We tend to put constants related to classes 、 Instance independent this The properties and methods of the static context are defined as , This avoids data redundancy , To improve the operation performance .

Be careful : We mentioned above that we do not depend on instances this The method of context can be defined as static method , This means that explicit annotations are required this Type can only be used in static methods this; Non static methods do not require explicit annotations this type , because this The default point is the instance of the class .

abstract class

Next, let's look at another feature about classes —— abstract class , It is a special class that cannot be instantiated and can only be inherited by subclasses .

We can use abstract classes to define the properties and methods that derived classes need to implement , You can also define other inherited default properties and methods , As shown in the following code :

abstract class Adder {
    
  abstract x: number;
  abstract y: number;
  abstract add(): number;
  displayName = 'Adder';
  addTwice(): number {
    
    return (this.x + this.y) * 2;
  }
}

class NumAdder extends Adder {
    
  x: number;
  y: number;
  constructor(x: number, y: number) {
    
    super();
    this.x = x;
    this.y = y;
  }
  add(): number {
    
    return this.x + this.y;
  }
}

const numAdder = new NumAdder(1, 2);
console.log(numAdder.displayName); // Adder
console.log(numAdder.add()); // 3
console.log(numAdder.addTwice()); // 6

adopt abstract keyword , We define an abstract class Adder, And pass abstract Keywords define abstract properties xy And methods add, And any inheritance Adder All the derived classes of need to implement these abstract properties and methods .

meanwhile , Still abstract classes Adder Defines non abstract attributes that can be inherited by derived classes displayName And methods addTwice.

then , In the code, the derived class that inherits the abstract class is defined NumAdder, And implements the abstract classes defined in x、y Abstract properties and add Abstract method . If a pair of... Is missing from the derived class x、y、add The implementation of any of the three abstract members , Then the code will prompt a ts(2515) error , If you are interested, you can verify it yourself .

Other non abstract members in an abstract class can be obtained directly through an instance , For example, through examples numAdder, We got displayName Properties and addTwice Method .

Because abstract classes cannot be instantiated , And derived classes must implement Abstract property and method definitions inherited from abstract classes , So the role of abstract classes is actually to encapsulate and abstract the basic logic .

The type of the class

The last feature of the class —— The type of the class is similar to that of the function , That is, when declaring classes , In fact, it also declares a special type ( To be exact, it is an interface type ), The name of this type is the class name , Represents the type of class instance ; When defining a class , All properties we declare except constructors 、 The type of the method is the member of this special type . As shown in the following code :

class A {
    
  name: string;
  constructor(name: string) {
    
    this.name = name;
  }
}
const a1: A = {
    }; // error TS2741: Property 'name' is missing in type '{}' but required in type 'A'.
const a2: A = {
     name: 'a2' };
原网站

版权声明
本文为[Large American without sugar]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/160/202206090433596859.html