Based on article
TypeScript Notes for Getting Started
Advanced article
1. Type alias
// Use type to give the type a new Name. type NameResolver = () => string; type NameOrResolver = Name | NameResolver; function getName(n: NameOrResolver): Name { if (typeof n === 'string') { return n; } else { return n(); }}Copy the code
Type aliases are often used to combine types.
Note: in the TS type definition, => is used to represent the function definition, the left side is the input type, need to be parenthesized, the right side is the output type. In ES6, => is called the arrow function.
2. String literal types
/ / string literals are defined with the type type type EventNames = 'click' | 'insensitive' | 'mousemove'; / / the type definition type alias type EventType = Element | null; function handleEvent(ele: EventType, event: EventNames) { // do something } handleEvent(document.getElementById('hello'), 'scroll'); HandleEvent (document.getelementById ('world'), 'dblclick'); // Error: event cannot be 'dblclick'Copy the code
Type aliases and string literal types are defined using type.
3. The tuples
Arrays combine objects of the same type, whereas meta-assemblies combine objects of different types.
Tuples originated in functional programming languages such as F#, where tuples are frequently used.
example
Define a pair of tuples of string and number:
let pany: [string, number] = ['pany', 25];
Copy the code
Note that the order of string and number is fixed
When assigning or accessing an element with a known index, the correct type is obtained:
let pany: [string, number] = ['pany', 25];
pany[0] = 'pany-ang';
pany[1] = 26;
pany[0].slice(1);
pany[1].toFixed(2);
Copy the code
When directly initializing or assigning to a variable of tuple type, all items specified in the tuple type need to be supplied:
let tom: [string, number];
tom = ['pany'];
// type '[string]' but required in type '[string, number]'.
Copy the code
Out of bounds element
When an out-of-bounds element is added, its type is limited to the combined type of each type in the tuple:
let pany: [string, number];
pany = ['pany', 25];
pany.push('male');
pany.push(true);
// Argument of type 'true' is not assignable to parameter of type 'string | number'.
Copy the code
4. The enumeration
The concept of TS enumerated types comes from C#
Enumeration types are used for scenarios that are limited to a certain range of values, such as seven days in a week, red, green, and blue colors.
4.1 constant term
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Sat"] === 6); // true
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[6] === "Sat"); // true
Copy the code
Enumerators are assigned an increasing number starting from 0, and the enumeration value is also mapped backwards to the enumeration name
4.2 Manual Assignment
enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 3); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Wed"] === 3); // true
console.log(Days[3] === "Sun"); // false
console.log(Days[3] === "Wed"); // true
Copy the code
Note: 1. Enumerators that are not manually assigned are incremented (+1) by the previous enumeration. 2. In the example above, the value of Days[3] is “Sun” and “Wed”, but TS does not report an error
Manually assigned items may not be numbers
Enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"S"};Copy the code
4.3 Calculated items
enum Color {Red, Green, Blue = "blue".length};
Copy the code
Here “blue”.length is a computed term.
Note: If the computed item is immediately followed by an item that is not manually assigned, it will report an error because it cannot obtain the initial value. All computed items are either the last item, or all subsequent items are manually assigned.
Enumerators are treated as constants if:
-
There is no initialization function and the previous enumerator is a constant. In this case, the current enumerator’s value is the value of the previous enumerator plus one. The first enumeration element is an exception. If it has no initialization method, its initial value is 0.
-
Enumerator members are initialized with constant enumeration expressions. Constant enumerated expressions are a subset of TypeScript expressions that can be evaluated at compile time. An expression is a constant enumerated expression when it satisfies one of the following conditions:
-
Numeric literal
-
Reference to a previously defined constant enumerator (which can be defined in a different enumeration type). If the member is defined in the same enumeration type, it can be referenced by an unqualified name
-
A bracketed constant enumeration expression
-
The +, -, ~ unary operators are applied to constant enumeration expressions
-
The +, -, *, /, %, < <, > >, > > >, &, |, ^ binary operators, constant enumeration expression as its an operation object. If the constant enumeration expression evaluates to NaN or Infinity, an error is reported at compile time
Enumerators in all other cases are treated as values that need to be computed.
4.4 Enumeration of Constants
Enumeration types defined with const enum:
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
Copy the code
Constant enumerations differ from normal enumerations in that they are deleted at compile time and cannot contain computed items.
The result of the above example is:
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
Copy the code
4.5 External Enumeration
Enumeration types defined with declare Enum:
declare enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
Copy the code
The type defined by DECLARE will only be used for compile-time checks and will be removed from the compilation result.
The result of the above example is:
var directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
Copy the code
Class 5.
5.1 Access Modifiers
TS can use three access modifiers, public, private, and protected.
-
Properties or methods decorated by public are public and can be accessed anywhere. By default, all properties and methods are public.
-
A property or method modified by private is private and cannot be accessed (including subclasses) outside the class in which it is declared.
-
Protected attributes or methods are protected, just like private, except that they are accessible in subclasses.
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
private
class Animal { private name: string; public constructor(name: string) { this.name = name; } } let a = new Animal('Jack'); console.log(a.name); a.name = 'Tom'; // Error: Property 'name' is private and only accessible within class 'Animal'Copy the code
When the constructor is modified private, the class is not allowed to be inherited or instantiated:
class Animal { public name: string; private constructor(name: string) { this.name = name; }} class extends Animal {constructor(name: string) {super(name); } } let a = new Animal('Jack'); // Cannot extend a class 'Animal'. Class constructor is marked as private. // constructor of class 'Animal' is private and only accessible within the class declaration.Copy the code
protected
When the constructor is protected, the class is only allowed to be inherited, not instantiated:
class Animal { public name: string; protected constructor(name: string) { this.name = name; } } class Cat extends Animal { constructor(name: string) { super(name); } } let a = new Animal('Jack'); Constructor of class 'Animal' is protected and only accessible within the class declaration.Copy the code
5.2 Parameter Properties
Modifiers and readonly can also be used in constructor arguments to assign a value to the property as defined in the class, making code more concise.
class Animal { // public name: string; public constructor(public name: string) { // this.name = name; }}Copy the code
5.3 readonly
Readonly is a read-only property keyword that is allowed only in property declarations or index signatures or constructors.
class Animal { readonly name: string; public constructor(name: string) { this.name = name; } } let a = new Animal('Jack'); console.log(a.name); // Jack a.name = 'Tom'; // Error: Cannot assign to 'name' because it is a read-only property.Copy the code
Note that readonly and other access modifiers need to be written after them if they exist at the same time.
class Animal { // public readonly name; public constructor(public readonly name: string) { // this.name = name; }}Copy the code
5.4 the abstract class
Abstract is used to define abstract classes and their abstract methods.
Note: Abstract classes are not allowed to be instantiated, and abstract methods in abstract classes must be implemented by subclasses.
abstract class Animal {
public name: string;
public constructor(name: string) {
this.name = name;
}
public abstract sayHi(): void;
}
class Cat extends Animal {
public sayHi() {
console.log(`Meow, My name is ${this.name}`);
}
}
let cat = new Cat('Tom');
cat.sayHi(); // "Meow, My name is Tom"
Copy the code
6. Classes and interfaces
As we learned earlier, interfaces can be used to describe the “shape of an object.”
This chapter focuses on another use of interfaces, abstracting part of the behavior of a class.
6.1 Classes implement interfaces
For example, a door is a class, and an anti-theft door is a subclass of a 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(): void; } 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
Of course, a class can only inherit from another class, but it can implement multiple interfaces.
6.2 Interface Inheritance Interface
interface Alarm {
alert(): void;
}
interface LightableAlarm extends Alarm {
lightOn(): void;
lightOff(): void;
}
Copy the code
LightableAlarm inherits Alarm and has two new methods, lightOn and lightOff, in addition to the alert method.
6.3 Interface Inheritance Type
In common object-oriented languages, interfaces cannot inherit from classes, but in TS they can:
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
Copy the code
Why TS supports interface inheritance classes: When we declare a class Point, we create a class named Point and a type named Point (the type of the instance).
7. The generic
Generics are the feature of defining functions, interfaces, or classes without specifying a specific type in advance.
7.1 Basic Examples
CreateArray Implements a function createArray that creates an array of specified length and populates each item with a default value: createArray createArray creates an array of specified length and populates each item with a default value: createArray createArray
function createArray(length: number, value: any): Array<any> {
let result = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
Copy the code
In the example above, we used the array generics mentioned earlier to define the type of the return value.
This code compiles without error, but an obvious flaw is that it does not define exactly the type of return value:
Array allows each entry of an Array to be of any type. But we expect that each item in the array should be the type of the input value.
Where generics come in handy:
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
Copy the code
We add T to the function name, where T is used to refer to any type of input, which can be used later in the input value: T and output Array.
7.2 Multiple Type Parameters
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
swap<number, string>([7, 'seven']); // ['seven', 7]
Copy the code
7.3 Generic Constraints
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
Copy the code
In the example above, we use extends to constrain that the generic T must conform to the Lengthwise shape of the interface, that is, it must contain the Length attribute. If you do not, then the generic T does not necessarily contain the length attribute, and the compilation will report an error.
7.4 Generic Interfaces
We learned that we can use interfaces to define the shape of a function. We can also use interfaces that contain generics to define the shape of a function:
interface CreateArrayFunc {
<T>(length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc;
createArray = function<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
Copy the code
Further, we can advance the generic parameter to the interface name:
interface CreateArrayFunc<T> {
(length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc<any>;
createArray = function<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
Copy the code
7.5 a generic class
class GenericNumber<T> { zeroValue! : T; add! : (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x: number, y: number): number { return x + y; }; Class GenericNumber<T> {constructor(public zeroValue: T, public add: (x: T, y: y) T) => T){ this.zeroValue = zeroValue; this.add = add; } } let myGenericNumber = new GenericNumber<number>(0, (x: number, y: number): number => { return x + y; });Copy the code
7.6 Default types of generic parameters
Default types come into play when type parameters are not specified directly in the code when using generics, and cannot be inferred from the actual value parameters:
function createArray<T = string>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
Copy the code
8. Declare the merger
If you define two functions, interfaces, or classes with the same name, they are merged into one type.
8.1 Function Combination
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
8.2 Interface Merging and Class Merging
Interface merging:
interface Alarm { price: number; alert(s: string): string; } interface Alarm { price: number; // weight: number; alert(s: string, n: number): string; }Copy the code
Is equivalent to:
interface Alarm {
price: number;
weight: number;
alert(s: string): string;
alert(s: string, n: number): string;
}
Copy the code
The merging of classes is consistent with the merging rules of interfaces.
The last
Don’t be stingy with your praise!
End.