TypeScript learning notes
Accumulate a little every day, persistence is harvest
One, the introduction
TS is a superset of JavaScript
- TypeScipt =
Type
+ JavaScript (add type system to JS)- TypeScript is a programming language developed by Microsoft and designed for the development of large-scale applications. It runs in any browser, on any computer, on any system
Second, the installation
2.1 installation TypeScript
Install typescript using commands
cnpm install -g typescript
Copy the code
2. Check the typescript version
$ tsc -v
Version 4.2.2
Copy the code
2.2 Installing the Development Environment
- Vscode: one of the most heavily used software for front-end development
- Live Server: indicates a real-time Server
- File:// AJAX requests don’t work for this protocol due to security restrictions, meaning that if your site gets content through JavaScript, you need a server.
- Automatically reloading pages after file changes can speed up development.
Basic grammar
3.1 the introduction
TypeScript consists of the following parts:
- The module
- function
- variable
- Statements and expressions
- annotation
3.2 The first TypeScript program
1. Create the runoob. ts file
var message:string = "Hello World"
console.log(message)
Copy the code
2. Run the compile command
tsc Runoob.ts
Copy the code
3, the results
// The runoob.js file is compiled
var message = "Hello World";
console.log(message);
Copy the code
The whole process is as follows:
Multiple files can be compiled:
tsc file1.ts file2.ts file3.ts
Copy the code
3.3 Reserved Keywords
TypeScript reserved keywords are shown in the following table:
break | as | catch | switch |
---|---|---|---|
case | if | throw | else |
var | number | string | get |
module | type | instanceof | typeof |
public | private | enum | export |
finally | for | while | void |
null | super | this | new |
in | return | true | false |
any | extends | static | let |
package | implements | interface | function |
new | try | yield | const |
continue | do |
3.4 pay attention to the point
-
Whitespace and line feeds
TypeScript ignores Spaces, tabs, and newlines in programs.
Spaces and tabs are often used to indent code to make it easier to read and understand.
-
TypeScript distinguishes between uppercase and lowercase characters
-
Sorting is optional
-
annotation
- Single-line comment (//) − All words following // are comments
- Multi-line comment (/* */) − This comment can span multiple lines
3.5 TypeScript object-oriented basics
TypeScript is an object-oriented programming language:
Object orientation has two main concepts: objects and classes
- Object: An object is an instance of a class, with state and behavior. For example, a dog is an object whose states are: color, name, breed; Behaviors include: wagging tail, barking, eating, etc.
- Class: A class is a template that describes the behavior and state of a class of objects.
- Methods: Methods are the implementation steps of a class’s operations.
Example:
class Site {
name():void {
console.log("Runoob")}}var obj = new Site();
obj.name();
Copy the code
compile
var Site = / * *@class * / (function () {
function Site() {
}
Site.prototype.name = function () {
console.log("Runoob");
};
returnSite; } ());var obj = new Site();
obj.name();
Copy the code
Result of executing JS
Runoob
Copy the code
4. Basic types
4.1 Table of Basic types
TypeScript includes the following data types:
The data type | The keyword | describe |
---|---|---|
Any type | any | A variable declared as any can be assigned a value of any type. |
Numeric types | number | Double precision 64 bit floating point value. It can be used to represent integers and fractions. |
String type | string | A series of characters, using single quotes (‘) or double quotation marks (“) to represent the string type. Backquotes’ to define multi-line text and inline expressions. |
Boolean type | boolean | Represents logical values: true and false.let flag: boolean = true; |
An array type | There is no | Declare variables as arrays. |
tuples | There is no | A tuple type is used to represent an array with a known number and type of elements. The types of each element need not be the same. |
The enumeration | enum | Enumeration types are used to define collections of values. |
void | void | Used to identify the type of value returned by a method, indicating that the method has no return value. |
null | null | Indicates that the object value is missing. |
undefined | undefined | Used to initialize a variable to an undefined value |
never | never | Never is a subtype of other types, including null and undefined, and represents a value that never occurs. |
** Note: **TypeScript and JavaScript do not have integer types.
4.2 Any type
A data type used when variables are not specified. It is commonly used in the following three cases:
-
When the value of a variable changes dynamically, such as the value entered by the user
let x: any = 4; x.ifItExists(); // Yes, the ifItExists method may exist at runtime, but it is not checked here x.toFixed(); / / right Copy the code
-
When changing existing code, the meaning allows optionally including or removing type checking at compile time, as shown in the following example:
let x: any = 4; x.ifItExists(); // Yes, the ifItExists method may exist at runtime, but it is not checked here x.toFixed(); / / right Copy the code
-
Example code for defining arrays that store various types of data is as follows:
let arrayList: any[] = [1.false.'fine']; arrayList[1] = 100; Copy the code
4.3 Null, and Undefined
Null:
Null in JavaScript means “nothing”.
Null is a special type with a single value. Represents an empty object reference.
Typeof null returns object.
Undefined:
- In JavaScript, undefined is a variable with no set value.
- Typeof a variable with no value returns undefined.
- Null and Undefined are subtypes of any other type, including void, and can be assigned to other types, such as numeric types, in which case the assigned type becomes Null or Undefined.
By enabling strictNullChecks in TypeScript, null and undefined can only be assigned to void or its own type
/ / enabled - strictNullChecks
let x: number;
x = 1; // Run correctly
x = undefined; // Error running
x = null; // Error running
Copy the code
In the example above, the variable x can only be a number. If a type may be null or undefined, | can be used to support a variety of types, the example code is as follows:
/ / enabled - strictNullChecks
let x: number | null | undefined;
x = 1; // Run correctly
x = undefined; // Run correctly
x = null; // Run correctly
Copy the code
4.4 never type
Never is a subtype of other types, including null and undefined, and represents a value that never occurs. This means that a variable declared to be of type never can only be assigned by type never, and in functions it usually behaves as an exception thrown or unable to execute to a termination point (such as an infinite loop), as shown in the following code:
let x: never;
let y: number;
// Error running. The numeric type cannot be converted to never
x = 123;
// The never type can be assigned to the never type
x = (() = >{ throw new Error('exception')}) ();// It works correctly. The never type can be assigned to a numeric type
y = (() = >{ throw new Error('exception')}) ();// A function that returns never can be the case where an exception is thrown
function error(message: string) :never {
throw new Error(message);
}
// A function that returns never can be a terminating point that cannot be executed
function loop() :never {
while (true) {}}Copy the code
Variable declaration
5.1 the introduction
TypeScript variable declaration rules:
- Variable names can contain both numbers and letters.
- Cannot contain any special characters, including Spaces, except the underscore _ and dollar $.
- Variable names cannot start with a number.
5.2 Variable Declaration
Variables must be declared before they are used. We can use var to declare variables in the following four ways:
1. Declare the variable’s type and initial value
// var [variable name] : [type] = value;
var uname:string = "Runoob";
Copy the code
2, declare the type of the variable, but do not have an initial value, the value of the variable will be undefined:
// var [variable name] : [type];
var uname:string;
Copy the code
3, declare a variable and initialize it, but do not set the type, the variable can be any type:
// var [variable name] = value;
var uname = "Runoob";
Copy the code
The type of a variable can be any type. The default initial value is undefined:
// var [variable name];
var uname;
Copy the code
5.3 Examples of variable declarations
var uname:string = "Runoob";
var score1:number = 50;
var score2:number = 42.50
var sum = score1 + score2
console.log("Name:"+uname)
console.log("First subject result:"+score1)
console.log("Second subject result:"+score2)
console.log("Total score:"+sum)
Copy the code
** Note: The ** variable should not use name otherwise it will have the same name as the name attribute under the global window object in the DOM.
Compile the above code using the TSC command, resulting in the following JavaScript code:
var uname = "Runoob";
var score1 = 50;
var score2 = 42.50;
var sum = score1 + score2;
console.log("Name:" + uname);
console.log("First subject result:" + score1);
console.log("Second subject result:" + score2);
console.log("Total score:" + sum);
Copy the code
Executing this JavaScript code produces the following output:
Name: Runoob50Second subject score:42.5Overall:92.5
Copy the code
TypeScript is strongly typed and will compile errors if you assign different types to variables, as shown in the following example:
var num:number = "hello" // This code will compile an error
Copy the code
5.4 Type Assertion
Type assertions can be used to manually specify the type of a value, that is, to allow variables to change from one type to another.
Syntax format:
< type > value
or
Value as type
var str = '1'
var str2:number = <number> <any> str // STR and str2 are strings
console.log(str2)
Copy the code
The compiled
var str = '1';
var str2 = str; // STR and str2 are strings
console.log(str2);
Copy the code
Output: 1.
5.5 Type Inference
When a type is not given, the TypeScript compiler uses type inference to infer the type.
If the type cannot be inferred due to a lack of declaration, its type is treated as the default dynamic ANY type.
var num = 2; // Type inferred to be number
console.log("The value of the num variable is+num);
num = "12"; // Error compiling
console.log(num);
Copy the code
-
The first line declares the variable num and = sets the initial value to 2. Note that the variable declaration does not specify a type. Therefore, the program uses type inference to determine the variable’s data type, assigning the first value to 2 and setting num to type number.
-
Third line of code, when we set the variable to a string value again, the compilation will fail. Because the variable is already set to type number.
error TS2322: Type '" 12" is not assignable to type 'number'.
Copy the code
5.6 Variable scope
The variable scope specifies the location of the variable definition.
The availability of variables in a program is determined by their scope.
TypeScript has the following scopes:
- Global scope – Global variables are defined outside the program structure and can be used anywhere in your code.
- Class scope − This variable can also be called a field. Class variables are declared inside a class, but outside the methods of the class. This variable can be accessed through an object of the class. Class variables can also be static, and static variables can be accessed directly by the class name.
- Local scope − Local variable. A local variable can only be used in a block of code (such as a method) that declares it.
var global_num = 12 // Global variables
class Numbers {
num_val = 13; // Instance variables
static sval = 10; // Static variables
storeNum():void {
var local_num = 14; // Local variables}}console.log("The global variable is:"+global_num)
console.log(Numbers.sval) // Static variables
var obj = new Numbers();
console.log("Instance variable:"+obj.num_val)
Copy the code
The above code was compiled to JavaScript using the TSC command as follows:
var global_num = 12; // Global variables
var Numbers = / * *@class * / (function () {
function Numbers() {
this.num_val = 13; // Instance variables
}
Numbers.prototype.storeNum = function () {
var local_num = 14; // Local variables
};
Numbers.sval = 10; // Static variables
returnNumbers; } ());console.log("The global variable is:" + global_num);
console.log(Numbers.sval); // Static variables
var obj = new Numbers();
console.log("Instance variable:" + obj.num_val);
Copy the code
Execute the above JavaScript code, and the output is:
The global variables are:12
10Instance variables:13
Copy the code
If we call the local variable local_num outside the method, we get an error:
error TS2322: Could not find symbol 'local_num'.
Copy the code
Operators
6.1 the introduction
TypeScript includes the following operations:
- Arithmetic operator
- Logical operator
- Relational operator
- Bitwise operators
- The assignment operator
- Ternary/conditional operator
- String operator
- Type operator
6.2 Arithmetic operators
Assuming y=5, the following table explains the operations of these arithmetic operators:
The operator | describe | example | X result | Y result |
---|---|---|---|---|
+ | add | x=y+2 | 7 | 5 |
– | subtraction | x=y-2 | 3 | 5 |
* | The multiplication | x=y*2 | 10 | 5 |
/ | division | x=y/2 | 2.5 | 5 |
% | Modulo (remainder) | x=y%2 | 1 | 5 |
++ | Since the increase | x=++y x=y++ |
6 5 |
6 6 |
— | Since the reduction of | x=–y x=y– |
4 5 |
4 4 |
6.3 Relational operators
The relational operator is used to evaluate whether the result is true or false.
X =5, the following table explains the operations of relational operators:
The operator | describe | To compare | The return value |
---|---|---|---|
= = | Is equal to the | x = =8 x==5 |
false true |
! = | Is not equal to | x! = 8 | true |
> | Is greater than | x>8 | false |
< | Less than | x<8 | true |
> = | Greater than or equal to | x>=8 | false |
< = | Less than or equal to | x<=8 | true |
6.4 Logical operators
Logical operators are used to determine logic between variables or values.
Given x=6 and y=3, the following table explains the logical operators:
The operator | describe | example |
---|---|---|
&& | and | (x < 10 && y > 1) is true |
|| | or | (x = = 5 | | y = = 5) to false |
! | not | ! (x = = y) to true |
Note: short-circuit operator (&& and | |) :
- && and | | operator expression can be used in combination. The && operator returns true only if both the left and right expressions are true.
- | | operators as long as one of the expression is true, then the combined expression will return true.
6.5 bit operators
Bitwise operation is the one – and two-bit operation of bitwise mode or binary number in programming.
The operator | describe | example | Similar to the | The results of | The decimal system |
---|---|---|---|---|---|
& | If two binary digits of the same length are 1, the result is 1; otherwise, 0. | x = 5 & 1 | 0101 & 0001 | 0001 | 1 |
| | OR, bitwise OR to process two binary numbers of the same length. As long as either of the two corresponding binary digits is 1, the result of that bit is 1. | x = 5 | 1 | 0101 | 0001 | 0101 | 5 |
~ | Invert, invert is a unary operator that performs a logical inverse operation on each bit of a binary number. Make the number 1 0 0 1. | x = ~ 5 | ~ 0101 | 1010 | – 6 |
^ | Xor, bitwise xor operation to perform a logical xor operation on each bit of a bitwise or binary number in an equal-length binary mode. The result of the operation is that the bit is 1 if one is different, and 0 otherwise. | x = 5 ^ 1 | 0101 ^ 0001 | 0100 | 4 |
<< | To move to the left, all the binary digits of the operands on the left of << are moved to the left by several bits. The number on the right of << specifies the number of bits to move. The high digit is discarded and the low digit is filled with 0. | x = 5 << 1 | 0101 < < 1 | 1010 | 10 |
>> | Move right, move all the binary digits of the >> left operand several right, and the number on the >> right specifies the number of digits moved. | x = 5 >> 1 | 0101 > > 1 | 0010 | 2 |
>>> | An unsigned right shift is similar to a signed right shift, except that a 0 complement is used on the left. | x = 2 >>> 1 | 0010 > > > 1 | 0001 | 1 |
Note: reverse ~ by bit
var temp = ~5;
Calculation steps:
5 binary 101, fill 32 in 00000000000000000000000000000101 to take the 11111111111111111111111111111010 because the 32-bit first is 1 in the beginning, so it’s a negative number, converts binary negative, Need to radix-minus-one complement after 00000000000000000000000000000101, converted to a decimal is 6 + 1 00000000000000000000000000000110, plus symbol turned negative – 6
Negative decimal to binary: Inverse plus one on the basis of the decimal absolute value source code
Such as:
How do I write negative 5 in binary if I take negative plus 1, 5 is 0000, 0101 negative 1111, 1010 plus 1, 1111, 1011 so this is negative 5, rightCopy the code
1111 1011 corresponds to the number of decimal
The first digit is 1, so it's a negative number minus 1, 1111, 1010, negative 0000, 0101 is 5 so the answer is negative 5Copy the code
6.6 Assignment Operators
Assignment operators are used to assign values to variables.
Given x=10 and y=5, the following table explains the assignment operators:
The operator | example | The instance | The x value |
---|---|---|---|
= (assign) | x = y | x = y | x = 5 |
+= (append first and then assign) | x += y | x = x + y | x = 15 |
-= (subtraction followed by assignment) | x -= y | x = x – y | x = 5 |
*= (multiply first and assign later) | x *= y | x = x * y | x = 50 |
/= (divide first and then assign) | x /= y | x = x / y | x = 2 |
Similar logic operator can also be associated with the assignment operator use: < < =, > > =, >, > =, & = | = ^ =.
6.7 Ternary Operators (?)
A ternary operation has three operands and needs to determine the value of a Boolean expression. The main purpose of this operator is to determine which value should be assigned to a variable.
Test ? expr1 : expr2
Copy the code
6.8 Type Operators
Typeof operator
Typeof is a unary operator that returns the data typeof the operand.
See the following example:
var num = 12
console.log(typeof num); // Output result: number
Copy the code
Compiling the above code using the TSC command yields the following JavaScript code:
var num = 12;
console.log(typeof num); // Output result: number
Copy the code
The output of the above example is as follows:
number
Copy the code
2. Instanceof: Used to determine whether the object is of the specified type
function Person(){};
var p =new Person();
console.log(p instanceof Person);//true
Copy the code
6.9 Other Operators
1. Negative operator (-)
To change the symbol of the operand, see the following example:
var x:number = 4
var y = -x;
console.log("X value is:",x); // Output result 4
console.log("Y value is:",y); // Output result -4
Copy the code
Compiling the above code using the TSC command yields the following JavaScript code:
var x = 4;
var y = -x;
console.log("X value is:", x); // Output result 4
console.log("Y value is:", y); // Output result -4
Copy the code
The output of the above example is as follows:
X value is:4The y value is: -4
Copy the code
String operators: concatenation operator (+)
The + operator can concatenate two strings. See the following example:
var msg:string = "RUNOOB"+".COM"
console.log(msg)
Copy the code
Compiling the above code using the TSC command yields the following JavaScript code:
var msg = "RUNOOB" + ".COM";
console.log(msg);
Copy the code
The output of the above example is as follows:
RUNOOB.COM
Copy the code
Seven, functions,
7.1 the introduction
Functions are the foundation of JavaScript applications. It helps you implement abstraction layers, mock classes, information hiding and modules. In TypeScript, although classes, namespaces, and modules are supported, functions are still the primary place to define behavior. TypeScript adds extra functionality to JavaScript functions to make them easier to use.
Like JavaScript, TypeScript functions can create named and anonymous functions. You’re free to choose what works for your application, whether it’s defining a series of API functions or using functions only once.
A simple example:
// Named function
function add(x, y) {
return x + y;
}
// Anonymous function
let myAdd = function(x, y) { return x + y; };
Copy the code
TypeScript function instances:
// Function definition
function greet() :string { // Returns a string
return "Hello World"
}
function caller() {
var msg = greet() // Call greet()
console.log(msg)
}
// Call the function
caller()
Copy the code
- Defines a function in an instance
greet()
, the return value is of typestring
greet()
Return a string
Compile the above code to get the following JavaScript code:
// Function definition
function greet() {
return "Hello World";
}
function caller() {
var msg = greet(); // Call greet()
console.log(msg);
}
// Call the function
caller();
Copy the code
7.2 Optional And Default Parameters
In TypeScript functions, if we define parameters, we must pass them in unless we make them optional. The optional parameters are identified by the question mark? .
function buildName(firstName: string, lastName: string) {
return firstName + "" + lastName;
}
let result1 = buildName("Bob"); // Error, missing argument
let result2 = buildName("Bob"."Adams"."Sr."); // Error, too many parameters
let result3 = buildName("Bob"."Adams"); / / right
Copy the code
Optional parameters
function buildName(firstName: string, lastName? :string) {
if (lastName)
return firstName + "" + lastName;
else
return firstName;
}
let result1 = buildName("Bob"); / / right
let result2 = buildName("Bob"."Adams"."Sr."); // Error, too many parameters
let result3 = buildName("Bob"."Adams"); / / right
Copy the code
The default parameters
The following example function has a default value of 0.50 for the parameter rate, which is used if no argument is passed when the function is called
function calculate_discount(price:number,rate:number = 0.50) {
var discount = price * rate;
console.log("Calculation result:",discount);
}
calculate_discount(1000)
calculate_discount(1000.0.30)
Copy the code
Compile the above code to get the following JavaScript code:
function calculate_discount(price, rate) {
if (rate === void 0) { rate = 0.50; }
var discount = price * rate;
console.log("Calculation result:", discount);
}
calculate_discount(1000);/ / 500
calculate_discount(1000.0.30);/ / 300
Copy the code
The remaining parameters
In the case where we do not know how many arguments to pass to the function, we can use the remaining arguments to define it.
The residual argument syntax allows us to pass in an indeterminate number of arguments as an array.
function buildName(firstName: string. restOfName:string[]) {
return firstName + "" + restOfName.join("");
}
let employeeName = buildName("Joseph"."Samuel"."Lucas"."MacKinzie");
Copy the code
The last named parameter of the restOfName function takes… Is prefixed as an array of remaining parameters, indexed from 0 (inclusive) to restofName.length (not included).
7.3 Anonymous Functions
An anonymous function is a function without a function name.
Anonymous functions are declared dynamically at runtime, just like standard functions, except that there is no function name.
We can assign an anonymous function to a variable, and the expression becomes a function expression.
var res = function(a:number,b:number) {
return a*b;
};
console.log(res(12.2))
Copy the code
Compile the above code to get the following JavaScript code:
var res = function (a, b) {
return a * b;
};
console.log(res(12.2)); / / 24
Copy the code
Anonymous function calls
(function () {
var x = "Hello!!";
console.log(x)
})()
Copy the code
7.4 Constructors
TypeScript also supports defining functions using JavaScript’s built-in constructor Function()
var myFunction = new Function("a"."b"."return a * b");
var x = myFunction(4.3);
console.log(x);
Copy the code
Compile the above code to get the following JavaScript code:
var myFunction = new Function("a"."b"."return a * b");
var x = myFunction(4.3);
console.log(x);/ / 12
Copy the code
7.5 Recursive functions
Recursive functions call the function itself from within the function.
Take an example: once upon a time there was a mountain, and there was a temple in the mountain. There was an old monk in the temple, telling a story to the young monk. What’s the story?” Once upon a time, there was a mountain. There was a temple in the mountain. There was an old monk telling a story to the young monk. What’s the story? ‘Once upon a time, there was a mountain in which there was a temple. In the temple, an old monk was telling a story to the young monk. What’s the story? … ‘”
function factorial(number) {
if (number< =0) { // Stop execution
return 1;
} else {
return (number * factorial(number - 1)); // Call itself}};console.log(factorial(6)); / / output 720
Copy the code
Compile the above code to get the following JavaScript code:
function factorial(number) {
if (number <= 0) { // Stop execution
return 1;
}
else {
return (number * factorial(number - 1)); // Call itself}};console.log(factorial(6)); / / output 720
Copy the code
7.6 Lambda functions
Lambda functions are also called arrow functions.
Arrow function expressions have a shorter syntax than function expressions.
var foo = (x:number) = >10 + x
console.log(foo(100)) // The output is 110
Copy the code
Compile the above code to get the following JavaScript code:
var foo = function (x) { return 10 + x; };
console.log(foo(100)); // The output is 110
Copy the code
A single parameter x can be defined like this
var display = x= > {
console.log("Output is"+x)
}
display(12)
Copy the code
Empty parentheses can be set with no arguments:
var disp =() = > {
console.log("Function invoked");
}
disp();
Copy the code
7.7 Function Overload
Overloading is when the method name is the same, but the parameter is different, and the return type can be the same or different.
Each overloaded method (or constructor) must have a unique list of parameter types.
The following example defines the difference between parameter type and parameter number
function disp(s1:string) :void;
function disp(n1:number,s1:string) :void;
function disp(x:any,y? :any) :void {
console.log(x);
console.log(y);
}
disp("abc")
disp(1."xyz");
Copy the code
Note:
If the parameter type is different, set the parameter type to any.
Different number of parameters you can make different parameters optional.
Viii. Key types
8.1 Array Array
Array declaration:
var array_name[:datatype]; / / declare
array_name = [val1,val2,valn..] / / initialization
Copy the code
The sample
var sites:string[];
sites = ["Google"."Runoob"."Taobao"]
Copy the code
8.2 Map object
The Map object holds key-value pairs and can remember the original insertion order of the keys.
Any value (object or raw value) can be a key or a value.
Map is a new data structure introduced in ES6. For details, see ES6 Map and Set.
Create a Map
let myMap = new Map(a);Copy the code
To initialize a Map, we can pass in key-value pairs as arrays:
let myMap = new Map([["key1"."value1"],
["key2"."value2"]]);Copy the code
Map-related functions and attributes:
- Map.clear () – Removes all key/value pairs from the map object.
- Map.set () – Sets the key-value pair and returns the map object.
- Map.get () – Returns the value of the key, or undefined if none exists.
- Map.has () – Returns a Boolean value that determines whether the map contains the value for the key.
- Map.delete () – To delete elements from a map, return true on success and false on failure.
- Map.size – Returns the number of key/value pairs of the Map object.
- Map.keys () – Returns an Iterator containing the keys of each element in the map.
- Map.values () – Returns a new Iterator containing the values of each element in the map.
Traverse Map
let nameSiteMapping = new Map(a); nameSiteMapping.set("Google".1);
nameSiteMapping.set("Runoob".2);
nameSiteMapping.set("Taobao".3);
// Iterate over keys in the Map
for (let key of nameSiteMapping.keys()) {
console.log(key);
}
// Iterate over the value in the Map
for (let value of nameSiteMapping.values()) {
console.log(value);
}
// Iterate over the Map key => value
for (let entry of nameSiteMapping.entries()) {
console.log(entry[0], entry[1]);
}
// Use object parsing
for (let [key, value] of nameSiteMapping) {
console.log(key, value);
}
Copy the code
Compiling with ES6:
tsc --target es6 test.ts
Copy the code
Compile the above code to get the following JavaScript code:
The instance
let nameSiteMapping = new Map(a); nameSiteMapping.set("Google".1);
nameSiteMapping.set("Runoob".2);
nameSiteMapping.set("Taobao".3);
// Iterate over keys in the Map
for (let key of nameSiteMapping.keys()) {
console.log(key);
}
// Iterate over the value in the Map
for (let value of nameSiteMapping.values()) {
console.log(value);
}
// Iterate over the Map key => value
for (let entry of nameSiteMapping.entries()) {
console.log(entry[0], entry[1]);
}
// Use object parsing
for (let [key, value] of nameSiteMapping) {
console.log(key, value);
}
Copy the code
Execute the above JavaScript code, and the output is:
Google
Runoob
Taobao
1
2
3
Google 1
Runoob 2
Taobao 3
Google 1
Runoob 2
Copy the code
8.3 Association Type
Joint type (Union Types) can be set through the pipe (|) variable Types, assignment can be assigned according to the type of set. Only the specified type can be assigned. An error is reported if any other type is assigned.
var val:string|number
val = 12
console.log("The number is"+ val)
val = "Runoob"
console.log("String as" + val)
Copy the code
TSC compiled to get js code:
var val;
val = 12;
console.log("The number is" + val);// The number is 12
val = "Runoob";
console.log("String as" + val);// The string is Runoob
Copy the code
Associative array
var arr:number[] |string[];
var i:number;
arr = [1.2.4]
console.log("** array of digits **")
for(i = 0; i<arr.length; i++) {console.log(arr[i])
}
arr = ["Runoob"."Google"."Taobao"]
console.log("** string array **")
for(i = 0; i<arr.length; i++) {console.log(arr[i])
}
Copy the code
TSC compiled js code:
var arr; var i; arr = [1, 2, 4]; Console. log("** numeric array **"); for (i = 0; i < arr.length; i++) { console.log(arr[i]); } arr = ["Runoob", "Google", "Taobao"]; Console. log("** string array **"); for (i = 0; i < arr.length; i++) { console.log(arr[i]); }Copy the code
Execution Result:
** Numeric array **1
2
4Runoob Google TaobaoCopy the code
Nine, interfaces,
9.1 the introduction
An interface is a declaration of a set of abstract methods, a collection of method characteristics that should be abstract and implemented by concrete classes. TypeScript interfaces are defined as follows:
interface interface_name {
}
Copy the code
9.2 Interface Instances
In the following example, we define an interface IPerson, followed by a variable customer of type IPerson.
Customer implements the attributes and methods of the interface IPerson.
interface IPerson {
firstName:string.lastName:string.sayHi: () = >string
}
var customer:IPerson = {
firstName:"Tom".lastName:"Hanks".sayHi: (a) :string= >{return "Hi there"}}console.log("The Customer object")
console.log(customer.firstName)
console.log(customer.lastName)
console.log(customer.sayHi())
var employee:IPerson = {
firstName:"Jim".lastName:"Blakes".sayHi: (a) :string= >{return "Hello!!!"}}console.log("The Employee object")
console.log(employee.firstName)
console.log(employee.lastName)
Copy the code
Note that the interface cannot be converted to JavaScript. It’s just a part of TypeScript.
Compile the above code to get the following JavaScript code:
var customer = {
firstName: "Tom".lastName: "Hanks".sayHi: function () { return "Hi there"; }};console.log("The Customer object");
console.log(customer.firstName);
console.log(customer.lastName);
console.log(customer.sayHi());
var employee = {
firstName: "Jim".lastName: "Blakes".sayHi: function () { return "Hello!!!"; }};console.log("The Employee object");
console.log(employee.firstName);
console.log(employee.lastName);
Copy the code
The output
Tom Hanks Hi there Employee Jim BlakesCopy the code
9.3 Combining Types and Interfaces
interface RunOptions {
program:string;
commandline:string[] |string| (() = >string);
}
// commandline is a string
var options:RunOptions = {program:"test1".commandline:"Hello"};
console.log(options.commandline)
Commandline is an array of strings
options = {program:"test1".commandline: ["Hello"."World"]};
console.log(options.commandline[0]);
console.log(options.commandline[1]);
Commandline is a function expression
options = {program:"test1".commandline:() = >{return "**Hello World**"; }};var fn:any = options.commandline;
console.log(fn());
Copy the code
Compile the above code to get the following JavaScript code:
// commandline is a string
var options = { program: "test1".commandline: "Hello" };
console.log(options.commandline);
Commandline is an array of strings
options = { program: "test1".commandline: ["Hello"."World"]};console.log(options.commandline[0]);
console.log(options.commandline[1]);
Commandline is a function expression
options = { program: "test1".commandline: function () { return "**Hello World**"; }};var fn = options.commandline;
console.log(fn());
Copy the code
The output is:
Hello
Hello
World
**Hello World**
Copy the code
9.4 Interfaces and Arrays
Interface we can set the index value and element of the array to different types. The index value can be a number or a string.
interface namelist {
[index:number] :string
}
var list2:namelist = ["John".1."Bran"] // Error element 1 is not a string
interface ages {
[index:string] :number
}
var agelist:ages;
agelist["John"] = 15 / / right
agelist[2] = "nine" / / error
Copy the code
9.5 Interface Inheritance
Interface inheritance: An interface can extend itself through other interfaces
- TypeScript interfaces can be multi-inherited
- The keyword used by inheritance
extends
Single inheritance syntax format
Child_interface_name extends super_interface_name
Copy the code
Multiple inheritance syntax format
Child_interface_name extendsSuper_interface1_name, super_interface2_name,... ,super_interfaceN_nameCopy the code
Single inherited instance
interface Person {
age:number
}
interface Musician extends Person {
instrument:string
}
var drummer = <Musician>{};
drummer.age = 27
drummer.instrument = "Drums"
console.log("Age:"+drummer.age)
console.log("Favorite instrument:"+drummer.instrument)
Copy the code
Compile the above code to get the following JavaScript code:
var drummer = {};
drummer.age = 27;
drummer.instrument = "Drums";
console.log("Age:" + drummer.age);
console.log("Favorite instrument:" + drummer.instrument);
Copy the code
Output result:
Age:27Favorite instrument: DrumsCopy the code
Multiple inheritance instance
interface IParent1 {
v1:number
}
interface IParent2 {
v2:number
}
interface Child extends IParent1, IParent2 { }
var Iobj:Child = { v1:12.v2:23}
console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
Copy the code
Compile the above code to get the following JavaScript code:
var Iobj = { v1: 12.v2: 23 };
console.log("value 1: " + Iobj.v1 + " value 2: " + Iobj.v2);
Copy the code
The output is:
value 1: 12 value 2: 23
Copy the code
Ten, class,
10.1 the introduction
Traditional JavaScript programs use functions and prototype-based inheritance to create reusable components, but it can be tricky for programmers familiar with the object-oriented approach because they use class-based inheritance and objects are built from classes. Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers will be able to use a class-based object-oriented approach. With TypeScript, we allow developers to use these features now and compile JavaScript to run on all major browsers and platforms, without waiting for the next JavaScript version.
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting; }}let greeter = new Greeter("world");
Copy the code
10.2 inheritance
In TypeScript, we can use common object-oriented patterns. One of the most basic patterns in class-based programming is to allow the use of inheritance to extend existing classes.
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`); }}class Dog extends Animal {
bark() {
console.log('Woof! Woof! '); }}const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
Copy the code
This example demonstrates basic inheritance: a class inherits properties and methods from a base class. Here, Dog is a derived class from the Animal base class through the extends keyword. A derived class is usually called a subclass, and a base class is usually called a superclass.
Because Dog inherits Animal functionality, we can create an instance of Dog that can bark() and move().
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`The ${this.name} moved ${distanceInMeters}m.`); }}class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters); }}class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters); }}let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
Copy the code
This example demonstrates some features not mentioned above. This time we use the extends keyword to create two subclasses of Animal: Horse and Snake.
Unlike the previous example, the derived class contains a constructor that must call super(), which executes the constructor of the base class. Also, we must call super() before accessing the this property in the constructor. This is an important rule that TypeScript enforces.
Xi. Objects
11.1 the introduction
An object is an instance that contains a set of key-value pairs. Values can be scalars, functions, arrays, objects, and so on, as shown in the following example
// The following objects contain scalars, functions, collections (arrays or tuples).
var object_name = {
key1: "value1"./ / a scalar
key2: "value".key3: function() {
/ / function
},
key4: ["content1"."content2"] / / collection
}
Copy the code
11.2 Type Template
Suppose we define an object in JavaScript:
var sites = {
site1:"Runoob".site2:"Google"
};
Copy the code
If we want to add methods to the object, we can make the following changes:
sites.sayHello = function(){ return "hello"; }Copy the code
Using the above approach in TypeScript causes compilation errors because objects in TypeScript must be instances of a specific type.
var sites = {
site1: "Runoob".site2: "Google".sayHello: function () {}// Type template
};
sites.sayHello = function () {
console.log("hello " + sites.site1);
};
sites.sayHello();
Copy the code
An object can also be passed to a function as an argument, as in the following example:
var sites = {
site1:"Runoob".site2:"Google"};var invokesites = function(obj: { site1:string, site2 :string }) {
console.log("site1 :"+obj.site1)
console.log("site2 :"+obj.site2)
}
invokesites(sites)
Copy the code
Compile the above code to get the following JavaScript code:
var sites = {
site1: "Runoob".site2: "Google"
};
var invokesites = function (obj) {
console.log("site1 :" + obj.site1);
console.log("site2 :" + obj.site2);
};
invokesites(sites);
Copy the code
Output result:
site1 :Runoob
site2 :Google
Copy the code
Namespaces
This article describes how to organize your code in TypeScript using namespaces (formerly called “internal modules”).
12.1 the introduction
One of the most explicit purposes of namespaces is to solve the duplication problem.
Suppose there are two students named Xiaoming in a class. In order to distinguish them clearly, we have to use some extra information besides their first names, such as their family names (Wang Xiaoming, Li Xiaoming), or their parents’ names, etc.
A namespace defines the visible scope of an identifier. An identifier can be defined in multiple namespaces, and its meaning in different namespaces is irrelevant. This way, any identifiers can be defined in a new namespace, and they will not conflict with any existing identifiers, because the existing definitions are in other namespaces.
In TypeScript, namespaces are defined as namespaces in the following syntax:
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName {}}Copy the code
The above defines a namespace, SomeNameSpaceName. If we need to call the classes and interfaces in SomeNameSpaceName externally, we need to add the export keyword to the classes and interfaces.
To call from another namespace, the syntax is:
SomeNameSpaceName.SomeClassName;
Copy the code
If a namespace is in a separate TypeScript file, it should be referenced with a triple slash /// in the following syntax:
/// <reference path = "SomeFileName.ts" />
Copy the code
The following example demonstrates the use of namespaces, defined in different files:
// ishape.ts
namespace Drawing {
export interfaceIShape { draw(); }}Copy the code
// circle.ts
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Circle implements IShape {
public draw() {
console.log("Circle is drawn"); }}}Copy the code
// Triangle. Ts file code:
/// <reference path = "IShape.ts" />
namespace Drawing {
export class Triangle implements IShape {
public draw() {
console.log("Triangle is drawn"); }}}Copy the code
// testShape.ts
/// <reference path = "IShape.ts" />
/// <reference path = "Circle.ts" />
/// <reference path = "Triangle.ts" />
function drawAllShapes(shape:Drawing.IShape) {
shape.draw();
}
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());
Copy the code
Compile the above code using the TSC command:
tsc --out app.js TestShape.ts
Copy the code
You get the following JavaScript code:
/// <reference path = "IShape.ts" />
var Drawing;
(function (Drawing) {
var Circle = / * *@class * / (function () {
function Circle() {
}
Circle.prototype.draw = function () {
console.log("Circle is drawn");
};
returnCircle; } ()); Drawing.Circle = Circle; })(Drawing || (Drawing = {}));/// <reference path = "IShape.ts" />
var Drawing;
(function (Drawing) {
var Triangle = / * *@class * / (function () {
function Triangle() {
}
Triangle.prototype.draw = function () {
console.log("Triangle is drawn");
};
returnTriangle; } ()); Drawing.Triangle = Triangle; })(Drawing || (Drawing = {}));/// <reference path = "IShape.ts" />
/// <reference path = "Circle.ts" />
/// <reference path = "Triangle.ts" />
function drawAllShapes(shape) {
shape.draw();
}
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());
Copy the code
Using the node command, the output is as follows:
$ node app.js
Circle is drawn
Triangle is drawn
Copy the code
12.2 Nested Namespaces
Namespaces support nesting, which means you can define a namespace in another namespace.
// Invoice. Ts file code:
namespace Runoob {
export namespace invoiceApp {
export class Invoice {
public calculateDiscount(price: number) {
return price * 40.; }}}}Copy the code
// InvoiceTest. Ts
/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice();
console.log(invoice.calculateDiscount(500));
Copy the code
Compile the above code using the TSC command:
tsc --out app.js InvoiceTest.ts
Copy the code
You get the following JavaScript code:
var Runoob;
(function (Runoob) {
var invoiceApp;
(function (invoiceApp) {
var Invoice = / * *@class * / (function () {
function Invoice() {
}
Invoice.prototype.calculateDiscount = function (price) {
return price * 40.;
};
returnInvoice; } ()); invoiceApp.Invoice = Invoice; })(invoiceApp = Runoob.invoiceApp || (Runoob.invoiceApp = {})); })(Runoob || (Runoob = {}));/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice();
console.log(invoice.calculateDiscount(500));
Copy the code
Using the node command, the output is as follows:
$ node app.js
200
Copy the code
12.3 the alias
One way to simplify namespace manipulation is to give commonly used objects short names using import q = X.Y.Z. Not to be confused with the import x = require(‘name’) syntax used to load modules, which creates an alias for the specified symbol. You can use this method to create aliases for arbitrary identifiers, including objects in imported modules.
namespace Shapes {
export namespace Polygons {
export class Triangle {}export class Square {}}}import polygons = Shapes.Polygons;
let sq = new polygons.Square(); // Same as "new Shapes.Polygons.Square()"
Copy the code
Note that instead of using the require keyword, we assign directly using the qualified name of the import symbol. This is similar to using VAR, but it also applies to types and imported symbols with namespace meaning. Importantly, for values, import generates a different reference than the original symbol, so changing the var value of the alias does not affect the value of the original variable.
12.4 External Namespaces
The popular library D3 defines its functionality in the global object D3. Because the library is loaded through a
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
}
export interface Event {
x: number;
y: number;
}
export interface Base extends Selectors {
event: Event; }}declare var d3: D3.Base;
Copy the code
Xiii. Modules
Term names have changed in TypeScript 1.5. “Internal modules” are now called “namespaces”. “External modules” are now shortened to “modules” in keeping with ECMAScript 2015 terminology (that is, module X {is equivalent to namespace X {as recommended).
13.1 the introduction
Starting with ECMAScript 2015, JavaScript introduced the concept of modules. TypeScript uses this concept as well.
- Modules execute in their own scope, not in the global scope
- use
export
Form exports internal functions, variables, classes, etc., making them externally visible and usable.- Other modules use
import
Form imports modules, using functions, variables, classes, etc.
Module export uses the keyword export, and the syntax format is as follows:
// File name: someinterface.ts
export interface SomeInterface {
// The code part
}
Copy the code
To use this module in another file, use the import keyword to import:
import someInterfaceRef = require("./SomeInterface");
Copy the code
13.2 export export
Rename: We may need a partial rename when exporting, which can be written as follows:
// Validation.ts
export interface StringValidator {
isAcceptable(s: string) :boolean;
}
Copy the code
// ZipCodeValidator.ts
class ZipCodeValidator implements StringValidator {
isAcceptable(s: string) {
return s.length === 5&& numberRegexp.test(s); }}export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };
Copy the code
Reexport: We often extend other modules and export only parts of that module. The re-export feature does not import that module in the current module or define a new local variable.
// ParseIntBasedZipCodeValidator.ts
export class ParseIntBasedZipCodeValidator {
isAcceptable(s: string) {
return s.length === 5 && parseInt(s).toString() === s; }}// Export the original validator but rename it
export {ZipCodeValidator as RegExpBasedZipCodeValidator} from "./ZipCodeValidator";
Copy the code
Or a module can wrap multiple modules and syndicate their exported content with the syntax: export * from “module”.
// AllValidators.ts
export * from "./StringValidator"; // exports interface StringValidator
export * from "./LettersOnlyValidator"; // exports class LettersOnlyValidator
export * from "./ZipCodeValidator"; // exports class ZipCodeValidator
Copy the code
13.3 the import import
Importing a module is as simple as exporting it. You can use one of the following import forms to import exports from other modules.
Import one of the exported contents in a module
import { ZipCodeValidator } from "./ZipCodeValidator";
let myValidator = new ZipCodeValidator();
Copy the code
You can rename the imported content
import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();
Copy the code
Import the entire module into a variable and access the exported part of the module through it
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
Copy the code
Import modules with side effects
Although this is not recommended, some modules will set some global state for other modules to use. These modules may not have any exports or the user may not care about its exports at all. Use the following method to import such modules:
import "./my-module.js";
Copy the code
13.4 Default Export
Each module can have a default export. The default export uses the default keyword tag; And a module can only have one default export. A special import form is required to import the default export.
The default export is very convenient. For example, a library like JQuery might have a default export of JQuery or $, and we’ll basically export JQuery with the same name or $.
// JQuery.d.ts
declare let $: JQuery;
export default $;
Copy the code
// App.ts
import $ from "JQuery";
$("button.continue").html( "Next Step..." );
Copy the code
Class and function declarations can be marked as default exports directly. The names of classes and functions marked as exported by default can be omitted. Such as:
// ZipCodeValidator.ts
export default class ZipCodeValidator {
static numberRegexp = / ^ [0-9] + $/;
isAcceptable(s: string) {
return s.length === 5&& ZipCodeValidator.numberRegexp.test(s); }}Copy the code
// Test.ts
import validator from "./ZipCodeValidator";
let myValidator = new validator();
Copy the code
Another example:
// StaticZipCodeValidator.ts
const numberRegexp = / ^ [0-9] + $/;
export default function (s: string) {
return s.length === 5 && numberRegexp.test(s);
}
Copy the code
// Test.ts
import validate from "./StaticZipCodeValidator";
let strings = ["Hello"."98052"."101"];
// Use function validate
strings.forEach(s= > {
console.log(`"${s}" ${validate(s) ? " matches" : " does not match"}`);
});
Copy the code
The default export can also be a value
// OneTwoThree.ts
export default "123";
Copy the code
// Log.ts
import num from "./OneTwoThree";
console.log(num); / / "123"
Copy the code
13.5 export =和import = require()
Both the CommonJS and AMD environments have an exports variable that contains all the exported content of a module.
Both CommonJS and AMD exports can be assigned to an object, in which case it acts like the export default in the ES6 syntax. The export Default syntax is not compatible with CommonJS and AMD exports, although it has similar functions.
To support CommonJS and AMD exports, TypeScript provides export = syntax.
Export = Syntax defines the export object of a module. The term object here refers to a class, interface, namespace, function, or enumeration.
To export a module using export =, you must import the module using TypeScript’s special syntax import Module = require(“module”).
// ZipCodeValidator.ts
let numberRegexp = / ^ [0-9] + $/;
class ZipCodeValidator {
isAcceptable(s: string) {
return s.length === 5&& numberRegexp.test(s); }}export = ZipCodeValidator;
Copy the code
// Test.ts
import zip = require("./ZipCodeValidator");
// Some samples to try
let strings = ["Hello"."98052"."101"];
// Validators to use
let validator = new zip();
// Show whether each string passed each validator
strings.forEach(s= > {
console.log(`"${ s }"-${ validator.isAcceptable(s) ? "matches" : "does not match" }`);
});
Copy the code
Sometimes, you only want to load a module under certain conditions. The compiler checks if each module is used in the generated JavaScript. If a module identifier is only used in the type annotation section and is not used at all in an expression, the code for requiring the module will not be generated. Omitting unused references is beneficial for performance and also provides the ability to selectively load modules.
The import XXX require(XXXX) is not used (or used in annotations) when TypeScript is compiled.
13.6 Use other JavaScript libraries
To describe the types of non-typescript libraries, we need to declare the apis exposed by the libraries.
We call it a declaration because it is not an implementation of an “external program.” They are usually defined in.d.ts files. If you are familiar with C/C++, you can think of them as.h files. Let’s look at some examples.
An external module
Most of the work in Node.js is done by loading one or more modules. We can use the top-level export declaration to define a.d.ts file for each module, but it is better to write it in a large.d.ts file. We use a similar approach to constructing an external namespace, except that we use the module keyword and enclose the name in quotes for later import. Such as:
// node.d.ts (simplified excerpt)
declare module "url" {
export interfaceUrl { protocol? :string; hostname? :string; pathname? :string;
}
export function parse(urlStr: string, parseQueryString? , slashesDenoteHost?) :Url;
}
declare module "path" {
export function normalize(p: string) :string;
export function join(. paths:any[]) :string;
export let sep: string;
}
Copy the code
Now we can ///
node.d.ts and use import url = require(“url”); Or import * as URL from “URL” to load the module.
/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");
Copy the code
External module abbreviation
If you don’t want to spend time writing a declaration before using a new module, you can use the shortened form of the declaration so that it can be used quickly
// declarations.d.ts
declare module "hot-new-module";
Copy the code
All exports in the shorthand module will be of type any.
import x, {y} from "hot-new-module";
x(y);
Copy the code
13.7 Do not use namespaces in modules
- A module has its own scope, and only exported declarations are visible outside the module. Namespaces are of little value when using modules.
- Modules themselves exist in the file system, and we must find them by path and file name. We can create
/collections/generic/
Folder, put the corresponding module in here.- Namespaces are used to resolve naming conflicts in global scopes,
My.Application.Customer.AddForm
andMy.Application.Order.AddForm
Both types have the same name but different namespaces.- There is no reason for two objects in a module to have the same name. From a module usage point of view, users will pick out the name they use to reference the module, so there is no reason for duplication.
13.8 Pit filling
The following are warning signs of module structure. Double check to make sure you are not using namespaces for modules:
- The top-level declaration of the file is
export namespace Foo { ... }
(deleteFoo
And move everything one level up) - There’s only one file
export class
orexport function
(Consider usingexport default
) - The top layer of multiple files has the same
export namespace Foo {
(Don’t assume these will merge into oneFoo
!)
Declaration Documents
14.1 the introduction
As a superset of JavaScript, TypeScript inevitably references other third-party JavaScript libraries during development. While you can call library classes and methods by direct reference, you can’t use TypeScript features like type checking. To solve this problem, you need to remove the function and method bodies from these libraries and leave only the export type declarations, resulting in a declaration file that describes the JavaScript library and module information. By referencing this declaration file, you can use the library file using various TypeScript features.
If we want to use a third-party library, such as jQuery, we usually get an element with id foo like this:
$('#foo');
/ / or
jQuery('#foo');// But in TypeScript, we don't know what $or jQuery are:
Copy the code
In this case, we need to use the DECLARE keyword to define its type to help TypeScript determine if the parameter type we passed is correct:
declare var jQuery: (selector: string) = > any;
jQuery('#foo');
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:
jQuery('#foo');
Copy the code
14.2 Declaration Document
Declaration files with the suffix.d.ts, for example:
runoob.d.ts
Copy the code
The syntax for declaring a file or module is as follows:
declare module Module_Name {
}
Copy the code
TypeScript introduces declarative file syntax formats:
/// <reference path = " runoob.d.ts" />
Copy the code
JQuery in DefinitelyTyped: jQuery in DefinitelyTyped: jQuery in DefinitelyTyped
14.3 instance
The following defines a third-party library to demonstrate:
// calcthirdpartyjslib.js file code:
var Runoob;
(function(Runoob) {
var Calc = (function () {
function Calc() {
}
})
Calc.prototype.doSum = function (limit) {
var sum = 0;
for (var i = 0; i <= limit; i++) {
sum = sum + i;
}
return sum;
}
Runoob.Calc = Calc;
return Calc;
})(Runoob || (Runoob = {}));
var test = new Runoob.Calc();
Copy the code
If we want to reference the above code in TypeScript, we need to set the declaration file calc.d. ts, which looks like this:
// calc.d. ts file code:
declare module Runoob {
export class Calc {
doSum(limit:number) : number; }}Copy the code
Declaration files don’t contain implementations, they’re just type declarations. Add declaration files to TypeScript:
// calctest.ts
/// <reference path = "Calc.d.ts" />
var obj = new Runoob.Calc();
// obj.doSum("Hello"); // Compilation error because we need to pass in numeric arguments
console.log(obj.doSum(10));
Copy the code
Use the TSC command to compile the above code file:
tsc CalcTest.ts
Copy the code
The generated JavaScript code looks like this:
// calctest.js:
/// <reference path = "Calc.d.ts" />
var obj = new Runoob.Calc();
//obj.doSum("Hello"); // Compilation error because we need to pass in numeric arguments
console.log(obj.doSum(10));
Copy the code
Finally, we write a runoob.html file and introduce the calctest.js file and the third party library calcthirdPartyjslib.js:
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8">
<title>Rookie tutorial (runoob.com)</title>
<script src = "CalcThirdPartyJsLib.js"></script>
<script src = "CalcTest.js"></script>
</head>
<body>
<h1>Declaration file test</h1>
<p>Novice test it out.</p>
</body>
</html>
Copy the code
Browser results:
15. Generics
15.1 the introduction
In software engineering, it is important not only to create consistent, well-defined apis, but also to consider reusability. The ability of components to support not only current data types but also future data types gives you a lot of flexibility when building large systems.
In languages like C# and Java, generics can be used to create reusable components that can support multiple types of data. This allows users to use components with their own data types.
15.2 Generic Hello World
Let’s create our first example of using generics: the identity function. This function returns any value passed to it. You can think of this function as the echo command.
Without generics, the function might look like this:
function identity(arg: number) :number {
return arg;
}
Copy the code
Alternatively, we use any to define functions:
function identity(arg: any) :any {
return arg;
}
Copy the code
Using any causes the function to accept arG arguments of any type, and some information is lost: the type passed in should be the same as the type returned. If we pass in a number, we just know that any type of value can be returned.
Therefore, we need a way to make the type of the return value the same as the type of the parameter passed in. Here, we use a type variable, which is a special variable that only represents a type, not a value.
function identity<T> (arg: T) :T {
return arg;
}
Copy the code
We add the type variable T to identity. T helps us capture the type passed in by the user (such as: number), which we can then use. Then we used T again as the return type. Now we know that the parameter type is the same as the return value type. This allows us to track information about the types used in functions.
We call this version of the Identity function generic because it can be applied to multiple types. Unlike using any, it does not lose information, as in the first example, which maintains accuracy, passing in the numeric type and returning the numeric type.
Once we have defined a generic function, we can use it in two ways. The first is to pass in all the arguments, including the type arguments:
let output = identity<string> ("myString"); // type of output will be 'string'
Copy the code
Here we explicitly specify that T is a string and is passed to the function as an argument, enclosed in <> instead of ().
The second method is more common. Makes use of type corollaries — that is, the compiler automatically helps us determine the type of T based on the arguments passed in:
let output = identity("myString"); // type of output will be 'string'
Copy the code
Note that we do not need to use Angle brackets (<>) to pass in the type explicitly; The compiler can look at the value of myString and set T to its type. Type inference helps us keep our code lean and readable. If the compiler cannot automatically infer the type, it can only pass in the type of T explicitly as above, which is possible in some complicated cases.
15.3 Using generic Variables
When creating a generic function like Identity using a generic type, the compiler requires that you use the generic type correctly in the function body. In other words, you must treat these parameters as any or all types.
Look at the previous identity example:
function identity<T> (arg: T) :T {
return arg;
}
Copy the code
If we want to print out the length of arg at the same time. We would probably do something like this:
function loggingIdentity<T> (arg: T) :T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
Copy the code
If we do this, the compiler will say we are using the.length attribute of the ARG, but there is no place to indicate that the ARG has this attribute. Remember, these type variables represent arbitrary types, so someone using this function could pass in a number that doesn’t have a.length attribute.
Now suppose we want to operate on an array of type T instead of T directly. Since we’re dealing with arrays, the.length property should be there. We can create this array just like any other array:
function loggingIdentity<T> (arg: T[]) :T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
Copy the code
You can think of the type of loggingIdentity like this: the generic function loggingIdentity takes the type parameter T and the parameter arg, which is an array of element type T, and returns an array of element type T. If we pass in an array of numbers, we return an array of numbers, because T is of type number. This allows us to use the generic variable T as part of the type, rather than the whole type, adding flexibility.
We could also implement the above example like this:
function loggingIdentity<T> (arg: Array<T>) :Array<T> {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
Copy the code
15.4 Generic types
The type of a generic function is no different from that of a non-generic function, except that there is a type parameter first, like a function declaration:
function identity<T> (arg: T) :T {
return arg;
}
let myIdentity: <T>(arg: T) = > T = identity;
Copy the code
We can also use different generic parameter names, as long as they match in number and usage.
function identity<T> (arg: T) :T {
return arg;
}
let myIdentity: <U>(arg: U) = > U = identity;
Copy the code
Generic interfaces:
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T> (arg: T) :T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
Copy the code
15.5 a generic class
Generic classes look much like generic interfaces. Generic classes use (<>) to enclose generic types after the class name.
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) = > T;
}
let myGenericNumber = new GenericNumber<number> (); myGenericNumber.zeroValue =0;
myGenericNumber.add = function(x, y) { return x + y; };
Copy the code
The GenericNumber class is fairly straightforward to use, and as you may have noticed, there is nothing limiting it to the number type. You can also use strings or other more complex types.
let stringNumeric = new GenericNumber<string> (); stringNumeric.zeroValue ="";
stringNumeric.add = function(x, y) { return x + y; };
console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
Copy the code
As with interfaces, placing generic types directly after classes helps us ensure that all attributes of a class are using the same type.
A class has two parts: a static part and an instance part. A generic class refers to the type of the instance part, so static attributes of the class cannot use this generic type.
15.6 Generic constraints
We want a function to output the length.length of the argument. To do this, we define an interface to describe the constraints. Create an interface that contains the.length attribute and use this interface and the extends keyword to implement the constraint:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise> (arg: T) :T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
Copy the code
Now the generic function is constrained, so it no longer applies to any type:
loggingIdentity(3); // Error, number doesn't have a .length property
Copy the code
We need to pass in values that match the constraint type and must contain the required attributes:
loggingIdentity({length: 10.value: 3});
Copy the code
Use type parameters in generic constraints
You can declare one type parameter and it is bound by another type parameter. For example, now we want to get the property from the object using the property name. And we want to make sure that this property exists on the object obj, so we need to use constraints between the two types.
function getProperty(obj: T, key: K) {
return obj[key];
}
let x = { a: 1.b: 2.c: 3.d: 4 };
getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
Copy the code
Use class types in Generics: When TypeScript uses generics to create factory functions, you need to reference the class type of the constructor. For instance,
function create<T> (c: {new(): T; }) :T {
return new c();
}
Copy the code
A more advanced example uses stereotype attributes to infer and constrain the relationship of a constructor to a class instance.
class BeeKeeper {
hasMask: boolean;
}
class ZooKeeper {
nametag: string;
}
class Animal {
numLegs: number;
}
class Bee extends Animal {
keeper: BeeKeeper;
}
class Lion extends Animal {
keeper: ZooKeeper;
}
function createInstance<A extends Animal> (c: new () => A) :A {
return new c();
}
createInstance(Lion).keeper.nametag; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
Copy the code
Xvi enumeration
16.1 the introduction
Using enumerations we can define constants with names. Use enumerations to clearly express intent or to create a differentiated set of use cases. TypeScript supports numeric and string-based enumerations.
16.2 Enumeration of digits
enum Direction {
Up = 1,
Down,
Left,
Right
}
Copy the code
As above, we define a numeric enumeration with Up initialized to 1. The rest of the members will automatically grow from 1. In other words, direction. Up is 1, Down is 2, Left is 3, and Right is 4.
We can also dispense with initializers altogether:
enum Direction {
Up,
Down,
Left,
Right,
}
Copy the code
Now, the Up value is 0, the Down value is 1 and so on. This self-growing behavior is useful when we don’t care about the value of the member, but be aware that the value of each enumerator is different.
Using enumerations is simple: access enumeration members by enumeration properties and access enumeration types by enumeration names:
enum Response {
No = 0,
Yes = 1,}function respond(recipient: string, message: Response) :void {
// ...
}
respond("Princess Caroline", Response.Yes)
Copy the code
Numeric enumerations can be mixed into calculated and constant members. Briefly, enumerations without initializers are either placed first or after enumerations initialized with numeric constants or other constants. In other words, the following situations are not allowed:
enum E {
A = getSomeValue(),
B, // error! 'A' is not constant-initialized, so 'B' needs an initializer
}
Copy the code
16.3 Enumeration of Strings
The concept of string enumerations is simple, but has subtle runtime differences. In a string enumeration, each member must be initialized with either a string literal or another string enumeration member.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",}Copy the code
Because string enumerations have no self-growing behavior, string enumerations can be serialized well. In other words, if you are debugging and have to read a number of enumeration values at runtime, this value is usually difficult to read – it doesn’t useful information (though reverse mapping will help), string enumeration allows you to provide the meaning of a runtime and readable values, independent of the members of the enumeration name.
16.4 Heterogeneous enumeration
Technically, enumerations can mix strings and numeric members, but it doesn’t seem like you’d do that:
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",}Copy the code
Unless you really want to take advantage of JavaScript runtime behavior, we don’t recommend doing so.
16.5 Computed and constant members
Each enumerator takes a value, which can be constant or computed. Enumerators are treated as constants if:
- It is the first member of the enumeration and has no initializer, in which case it is assigned a value
0
:
// E.X is constant:
enum E { X }
Copy the code
- It has no initializer and its preceding enumerator is onedigitalConstants. In this case, the value of the current enumerator is incremented by the value of its previous enumerator.
// All enum members in 'E1' and 'E2' are constant.
enum E1 { X, Y, Z }
enum E2 {
A = 1, B, C
}
Copy the code
- Enumerator useConstant enumeration expressionInitialization. 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:
- An enumerated expression literal (mainly a string literal or a number literal)
- A reference to a previously defined constant enumerator (which can be defined in a different enumeration type)
- A bracketed constant enumeration expression
- Unary operator
+
.-
.~
One of them applies to constant enumeration expressions - Constant enumeration expressions as binary operators
+
.-
.*
./
.%
.<<
.>>
.>>>
.&
.|
.^
Operation object of. If the constant enumeration expression is evaluatedNaN
orInfinity
, an error is reported at compile time.
Enumerators in all other cases are treated as values that need to be computed.
enum FileAccess {
// constant members
None,
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
// computed member
G = "123".length
}
Copy the code
16.6 Reverse Mapping
In addition to creating an object with attribute names as object members, numeric enumerators also have reverse mapping from enumeration values to enumeration names. For example, in the following example:
enum Enum {
A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
Copy the code
TypeScript might compile this code into JavaScript:
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[a]; // "A"
Copy the code
In the generated code, the enumeration type is compiled into an object that contains both a forward mapping (name -> value) and a reverse mapping (value ->name). Reference enumerators are always born to access properties and are never inlined.
Note that no reverse mapping is generated for string enumerators.
16.7 const enumeration
In most cases, enumerations are a very efficient solution. In some cases, however, the requirements are strict. To avoid the overhead in extra generated code and additional indirect access to enumeration members, we can use const enumerations. Constant enumerations are defined by using a const modifier on the enumeration.
const enum Enum {
A = 1,
B = A * 2
}
Copy the code
Constant enumerations can only use constant enumeration expressions, and unlike regular enumerations, they are removed at compile time. Constant enumerators are inlined where they are used. This can be done because constant enumerations are not allowed to contain computed members.
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
Copy the code
The generated code is:
var directions = [0 /* Up */.1 /* Down */.2 /* Left */.3 /* Right */];
Copy the code
16.8 External Enumeration
An external enumeration is used to describe the shape of an existing enumeration type.
declare enum Enum {
A = 1,
B,
C = 2
}
Copy the code
There is an important difference between external and non-external enumerations. In normal enumerations, members that have no initialization methods are treated as constant members. External enumerations of nonconstant numbers are treated as computations when there is no initialization method.