This is the 26th day of my participation in the August Text Challenge.More challenges in August
The articles
Typescript Notes (1)
The last article introduced typescript’s basic types and a few other things, but this article will document some of the common features of TS.
Types of assertions
A type assertion, in short, is a statement about the type of a variable.
Var times = 2; The Times variable in this statement life is of type Number.
Of course some people say I know ah, I wrote the code myself can I not know? The assertion poem is for TS. Ts uses assertions to help you determine if there is a problem in your code logic, and others can quickly understand the meaning of these variables through type assertions in your code.
In short, type assertion is an awesome feature of TS. It’s like a heifer on a rocket
So how do you use type assertions in typescript?
let sth: any = 'this are sth special here'
Copy the code
Since STH is an arbitrary type, it may or may not have the length attribute, and if we want to read the length attribute, we need to assert that it is a string. There are two approaches, the second of which must be used in TSX
let sthLength: number = (<string>sth).length
let sthLength2: number = (sth as string).length
Type inference
Writing type assertions for each variable is a huge waste of time, and TS clearly understands this, so IT provides type inference.
The so-called type inference means that when we write code to define a variable, we do not have to specify the type explicitly. Later, TS can automatically change the type of the variable according to the value of the variable. Therefore, type inference requires that the variable must be assigned when it is defined
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7; //error
Copy the code
If there is no assignment at the time of the definition, it is inferred to be of type any regardless of whether there is a subsequent assignment or not and is not typed at all
let myFavoriteNumber;
myFavoriteNumber = 'seven'; //OK
myFavoriteNumber = 7; //ok
Copy the code
The joint type
In many cases, the type of a variable is not necessarily fixed. For example, we often initialize an interval execution:
var timer = null
timer = setTimeout(console.log, 1000)
Copy the code
In view of this situation, TS introduced the concept of joint type, which is used to indicate that the value range of a variable can be one or a set of several types.
let myFavoriteNumber: string | number;
Copy the code
When TypeScript doesn’t know what type a variable of a union type is, we can only access properties or methods that are common to all types of the union type
function getLength(something: string | number) :number {
something.length; //error
something.toString(); //ok
}
Copy the code
In addition, when a variable that has been defined as a union type is assigned, TS will infer a definite type according to the rules of type inference
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); / / 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); //error
Copy the code
interface
Interface is a description of a thing in essence, there is no concept of object-oriented programming in JS itself, so through the description of the object or function, thus forming a convention on the level of using the object or function.
To distinguish the interface from ordinary variables such as object functions, the interface is capitalized and the shape of the variable must be the same as that of the interface when assigning values.
So, interfaces can be used in three ways:
- Used to abstract part of a class’s behavior,
- Also used to describe the Shape of an object, such as a function,
- It can also be used to mix the two.
interface Person {
name: string;
age: number;
}
interface Sum{
(x:number.y:number) :number
}
let sum:Sum = (a,b) = > { return a+b }
Copy the code
Arbitrary and optional properties
But generally speaking, a defined object is not used the same as its definition, in which case the interface definition can use optional attributes as well as arbitrary attributes.
Are optional attributes used? Arbitrary attributes are represented by []
interfacePerson { age? :string; // Optional attributes
}
interface Animal {
[propName: string] :string; // An arbitrary attribute
}
Copy the code
Note: If any attribute is defined, the type of both the determined attribute and the optional attribute must be a subset of its type
interface Person {
[propName: string] :string; // The value type of any attribute is stringage? :number; //error The number type is not correct because any attribute is defined as string
}
Copy the code
Read-only property
Sometimes we want to define a property in an object that cannot be changed by the outside world. The implication is that the property is read-only, so read-only properties are used here
Read-only property: Readonly can be used to define that a property is read-only and cannot be reassigned
interface Person {
readonly id: number;
}
let tom: Person = {
id: 89757
}
tom.id = 1 //error
Copy the code
Interface inheritance
The three basic characteristics of phase objects are inheritance, encapsulation and polymorphism.
In order to better support JS object-oriented programming, TS specifies that interfaces can be inherited. Inheritance is represented by extends.
Let’s say we have a base class called shape, and that shape has a color property
interface Shape {
color: string
}
Copy the code
Then we need to implement a quadrilateral interface that inherits the shape base class to get the color property
interface Square extends Shape {
sideLength: number
}
let square = {} as Square
square.color = 'blue'
square.sideLength = 10
Copy the code
Inheritance can be one-to-many, that is, an interface can inherit from multiple interfaces
interface PenStroke extends Shape, Square{
width: number
}
Copy the code
An array of class
Array and ordinary arrays, array is only has the attributes of the index and the length of the object, such as document. GetElementsByClass return values
Therefore, class arrays should not be defined as normal arrays, but as interfaces.
Ts has defined interfaces for class arrays, so we can use them directly, such as IArguments, NodeList, HTMLCollection, HTMLElement, etc
function sum() {
let args: IArguments = arguments;
}
var p:HTMLElement = document.createElement('p')
Copy the code
Built-in objects
Built-in object types include several basic and complex types, as well as Date and Error.
In TypeScript, variables are defined as built-in object types, such as an error
let e: Error = new Error('Error occurred');
Copy the code
Or define a date type
let d: Date = new Date(a);Copy the code
Or regular expressions
let r: RegExp = /[a-z]/;
Copy the code
At the same time, JS also has two very important built-in objects, that is DOM and BOM, I believe that all students who have learned javascrit, are impressed by these two objects.
DOM and BOM provide built-in objects such as Document, HTMLElement, Event, NodeList, etc
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click'.function(e: MouseEvent) {
// Do something
})
Copy the code
function
The biggest difference between a function and other variables is that a function has inputs and outputs.
To constrain this in TypeScript, you need to take into account both input and output.
Function constraints provided by TS are also divided into two types, one is function declaration, the other is function expression.
Where, the function declaration is written as follows:
function sum(x: number, y: number) :number {
return x + y;
}
Copy the code
Function expressions are written slightly differently, because expressions also need to describe declared function variables
let mySum: (x: number, y: number) = > number = function (x: number, y: number) :number {
return x + y;
};
Copy the code
(x: number, y: number) => number
Note that the => in the function expression above is different from the arrow function in ES6, where the left side of the => represents the constraint on the function’s input and the right side represents the constraint on the function’s output
Of course, this is often confusing to the reader, so TS provides an alternative description
Use interfaces to constrain functions
We can also use interfaces to constrain functions, which we wrote about earlier, which might look a little bit better than expressions
interface MySum {
(x: number.y: number) :number;
}
let sum: MySum = function(x: number, y: number) {
return x + y
}
Copy the code
Optional parameters
Sometimes, especially in plug-in encapsulation of methods, some parameters are not mandatory, and if the user does not pass such parameters, we can assign them internally by default
So ts provides optional arguments.
Optional argument: also used in functions? To describe optional parameters, which are placed after required parameters
function buildName(firstName: string, lastName? :string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName + 'Cat'; }}let tomcat = buildName('Tom'.'Cat');
let tom = buildName('Tom');
Copy the code
Parameter Default Value
ES6 adds the use of default values for function arguments (a=1)=>a++
In this case, TS uses the parameter defaults to constrain.
Parameter defaults: TypeScript recognizes parameters with default values as optional, so there is no constraint that optional parameters must be followed by required parameters
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom'.'Cat');
let cat = buildName(undefined.'Cat');
Copy the code
Parameter deconstruction assignment
At the same time, TS’s deconstruction of ES6 also provides constraint writing
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1.2.3);
Copy the code
Function overloading
Function overloading: function overloading is a special case of a function. For ease of use, C++ allows several functions of the same name to be declared in the same scope, but the formal arguments (the number, type, or order of the arguments) of these functions must be different. That is, the same function performs different functions.
However, there is no concept of function overloading in javascript, and the function variable declared after will overwrite the previous variable of the same name, so we usually implement pseudo-overloading by judging the parameters
function reverse(x: number) :number;
function reverse(x: string) :string;
function reverse(x: number | string) :number | string {
if (typeof x === 'number') {
return Number(x.toString().split(' ').reverse().join(' '));
} else if (typeof x === 'string') {
return x.split(' ').reverse().join(' '); }}Copy the code
In the code above, we repeat the function reverse multiple times, the first several times as a function definition, and the last time as a function implementation.
TypeScript matches function definitions first, so multiple function definitions with inclusion relationships need to have the exact definition first
Mixing interfaces and functions
Interfaces can be used to mix classes and functions.
This is because you can define both properties and methods that belong to a class.
interface Counter {
(start: number) :string
interval: number
reset(): void
}
function getCounter() :Counter {
let counter = (function (start: number) {})as Counter
counter.interval = 123
counter.reset = function () {}return counter
}
let c = getCounter()
c(10)
c.reset()
c.interval = 5
Copy the code
class
ES6 provides the concept of classes to make it easier to use object-oriented programming ideas.
Classes can be seen as the most basic units in the program, such as tank battles, tanks can be seen as classes, bullets can be seen as classes, walls can be seen as classes.
So the class itself can define multiple properties and methods. For each property and method, there are additional constraints, such as whether the property is public or private, in addition to its own type constraints.
The modifier
There are many types of modifiers for classes:
The modifier | meaning | note |
---|---|---|
public | Public property or method | Access at will |
private | Private properties or methods | Not accessible from outside, not inheritable |
protected | A protected property or method | Can only be inherited |
static | Static properties or methods | Exists only in the class itself |
readonly | Read-only property or method | Must be initialized at declaration time or in a constructor |
abstract | Abstract classes or methods | Abstract classes cannot be instantiated; abstract methods must be implemented by subclasses |
Properties or methods decorated by public are public, can be accessed anywhere, and can be inherited. By default, all properties and methods are public
class Animal {
public name: string;
public constructor(name: string) {
this.name = name; }}let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom';
console.log(a.name); // Tom
Copy the code
A property or method modified by private is private, cannot be accessed outside the class in which it is declared, and cannot be inherited
class Animal {
private name: string;
public constructor(name: string) {
this.name = name; }}let a = new Animal('Jack');
console.log(a.name); // error
a.name = 'Tom'; //error
class Cat extends Animal {
constructor(name) {
super(name);
console.log(this.name); //error}}Copy the code
When the constructor’s modifier is private, the class is not allowed to be inherited or instantiated
class Animal {
public name: string;
private constructor (name: string) {
this.name = name; }}class Cat extends Animal { //error
constructor (name) {
super(name); }}let a = new Animal('Jack');//error
Copy the code
When the constructor is protected, the class is only allowed to be inherited
class Animal {
public name: string;
protected constructor (name: string) {
this.name = name; }}class Cat extends Animal {
constructor (name) {
super(name); }}let a = new Animal('Jack'); //error
Copy the code
Protected attributes or methods are protected, just like private, except that they are accessible in subclasses
class Animal {
protected name: string;
public constructor(name: string) {
this.name = name; }}class Cat extends Animal {
constructor(name) {
super(name);
console.log(this.name); //ok}}Copy the code
Static is a proposal in ES7 that defines static properties that exist on the class itself rather than on an instance of the class
class Animal {
static num: number = 42;
constructor() {
// ...}}console.log(Animal.num); / / 42
Copy the code
Readonly A read-only property that must be initialized at declaration time or in a constructor
class Person {
readonly age: number
constructor(public readonly name: string, age: number) {
this.name = name
this.age = age
}
}
let a = new Animal('Jack'.25);
console.log(a.name); // Jack
a.name = 'Tom'; //error
a.age = 26; //error
Copy the code
Abstract is used to define abstract classes and their methods. First, abstract classes are not allowed to be instantiated, and second, abstract methods in abstract classes must be implemented by subclasses
abstract class Animal {
public name: string;
public constructor(name) {
this.name = name;
}
public abstract sayHi(): void;
}
let a = new Animal('Jack'); //error
class Cat extends Animal {
public sayHi(): void { // The inherited class must implement this method
console.log(`Meow, My name is The ${this.name}`);
}
public eat(): void {
console.log(`The ${this.name} is eating.`); }}let cat = new Cat('Tom');
Copy the code
Accessors: Use getters and setters to change the assignment and read behavior of properties
// Check whether the user password is correct before allowing the user to modify the employee information
class Employee {
private _fullName: string
private _passcode: string
constructor(readonly passcode: string){
this._passcode = passcode
}
get fullName() :string {
return this._fullName
}
set fullName(newName: string) {
if (this._passcode && this._passcode == 'secret passcode') {
this._fullName = newName
}
else {
console.log('Error: Unauthorized update of employee! ')}}}let employee = new Employee('secret passcode')
employee.fullName = 'Bob Smith'
if (employee.fullName) {
console.log(employee.fullName)
}
Copy the code
Interface with the class
Classes are allowed wherever interfaces are allowed
class Point {
x: number
y: number
}
interface Point3d extends Point {
z: number
}
let point3d: Point3d = {x: 1.y: 2.z: 3}
Copy the code
Class implementation interface
Interfaces can be used not only to describe attributes of a class, but also to implement class methods, which are called class-implementation interfaces.
If there are features common to different classes, you can extract them as interfaces using the implements keyword.
For example: door is a class, security door is a subclass of door. If the security door has an alarm function, we can simply add an alarm method to the security door. At this time, if there is another class, car, also has the function of alarm, you can consider the alarm extraction, as an interface, security door and car to achieve it
interface Alarm {
alert();
}
class door {}class SecurityDoor extends door implements Alarm {
alert() {
console.log('SecurityDoor alert'); }}class Car implements Alarm {
alert() {
console.log('Car alert'); }}Copy the code
The same class can also implement multiple interfaces, making it possible to add multiple constraints to the class.
interface Alarm {
alert();
}
interface Light {
lightOn();
lightOff();
}
class Car implements Alarm.Light {
alert() {
console.log('Car alert');
}
lightOn() {
console.log('Car light on');
}
lightOff() {
console.log('Car light off'); }}Copy the code
Interface inheritance class
As mentioned earlier, interfaces can inherit from each other, but interfaces can also inherit from classes.
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1.y: 2.z: 3};
Copy the code