This code runs under version V4.2.3 and defaults to strict mode
Introduction to the
This article is an improvement on the TypeScript tutorial. The original code executes in “non-strict mode.” Here I’ve changed it to code that works in “strict mode” and streamlined many sections.
Hello World
Open the TS online editor and execute the code:
function fn(param: string) {
return param
}
console.log(fn('Hello World'))
Copy the code
Compiled JS code:
function fn(param) {
return param;
}
console.log(fn('Hello World'));
Copy the code
Console output:
"Hello World"
Copy the code
The basic concept
-
In TS, use: to specify the type of a variable.
-
TS statically checks types only at compile time, not at run time.
-
Tsconfig. json: noEmitOnError: tsconfig.json: noEmitOnError: tsconfig.json: noEmitOnError
Based on article
1. Raw data type
There are two types of JS: raw data types and object types.
Primitive data types include: Boolean, numeric, string, NULL, undefined, Symbol, and BigInt.
The top five applications in TS:
1.1 Boolean value
Define a Boolean value type using Boolean:
let isDone: boolean = false;
console.log(isDone)
Copy the code
Calling Boolean directly also returns a Boolean type:
let createdByBoolean: boolean = Boolean(1);
Copy the code
But new Boolean() returns a Boolean object:
let createdByNewBoolean: Boolean = new Boolean(1);
Copy the code
Note:
In TS, Boolean is the basic type in JS, and Boolean is the constructor in JS. The other basic types (except null and undefined) are not mentioned here.
1.2 numerical
Define numeric types using number:
let decLiteral: number = 6; let hexLiteral: number = 0xf00d; // let binaryLiteral: number = 0b1010; // let octalLiteral: number = 0o744; // 484 let notANumber: number = NaN; let infinityNumber: number = Infinity;Copy the code
Compile result:
let decLiteral = 6; let hexLiteral = 0xf00d; // let binaryLiteral = 0b1010; // let octalLiteral = 0o744; // 484 let notANumber = NaN; let infinityNumber = Infinity;Copy the code
1.3 the string
Use string to define a string type:
let myName: string = 'pany';
Copy the code
1.4 Void
JS has no concept of void. In TS, void can be used to represent a function that does not return any value:
function logName(): void {
console.log('pany')
}
Copy the code
It is useless to declare a void variable because you can only assign it undefined: void void
let unusable: void = undefined;
Copy the code
1.5 Null, and Undefined
In TS, null and undefined can be used to define these two primitive data types:
let u: undefined = undefined;
let n: null = null;
Copy the code
2. Any value (Any)
If it is a common type, it is not allowed to change the type during assignment:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
// Type 'number' is not assignable to type 'string'.
Copy the code
If it is of any type, however, it is allowed to be assigned to any type:
let myFavoriteNumber: any = 'seven'; myFavoriteNumber = 7; // Compilation succeededCopy the code
It is allowed to access any property or method on any value, and after declaring a variable as any value, any operation on it returns the type of any value:
let anyThing: any = 'pany'; anyThing.myName; anyThing.setName('pany-ang'); // The above code does not have a compile-time error, but does have a runtime errorCopy the code
A variable is recognized as any value type if its type is not specified when it is declared:
let something; something = 'seven'; something = 7; console.log(something); / / 7Copy the code
3. Type inference
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
// Type 'number' is not assignable to type 'string'.
Copy the code
The above code is equivalent to:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
Copy the code
That is, TS will infer a type when there is no explicit type specified. This is called type inference.
If defined without an assignment, it is inferred to be of type any, as in the previous section: Any value
4. Union type
The joint type | separated for each type of use:
let myFavoriteNumber: string | number; myFavoriteNumber = 'seven'; myFavoriteNumber = 7; // Compilation succeededCopy the code
The string here | number means, is of type string or number.
When TS is not sure what type a variable of the union type is, it can only access properties or methods that are common to all types of the union type:
function getLength(something: string | number): number { return something.length; / / a compilation error, because the length is not a common attribute} function get string (something: string | number) : string {return something. The toString (); // Compiled successfully}Copy the code
5. Object type (interface)
In object-oriented languages, interfaces and interfaces are abstractions of behavior, and classes are required to implement the behavior.
The interface in TS is a very flexible concept. In addition to abstracting part of the behavior of a class, it is often used to describe the shape of an object.
Interface Person {name: string; age: number; } let pany: Person = {name: 'pany', age: 25};Copy the code
Optional attributes of the interface:
interface Person { name: string; age? : number; // Optional attribute age} let pany: Person = {name: 'pany'}; // Compilation succeededCopy the code
Any attributes of the interface:
interface Person { name: string; age? : number; [propName: string]: any; } let pany: Person = {name: 'pany', gender: 'male'};Copy the code
Note 1: If any attribute is defined and the attribute is of type string (in addition to number, which is often used in class arrays), the type of both the attribute and the optional attribute must be a subset of its attribute value type
interface Person { name: string; age? : number; [propName: string]: string; } let pany: Person = { name: 'pany', age: 25, gender: 'male' }; // Compilation error // Because the type (number) of the optional attribute age is not a subtype of the type (string) of any attributeCopy the code
Note 2: An interface can have only one arbitrary attribute. If the interface has more than one type of attribute, you can use the union type in any attribute
interface Person { name: string; age? : number; [propName: string]: string | number | undefined; } let pany: Person = { name: 'pany', age: 25, gender: 'male' }; // Compilation succeededCopy the code
Read-only property
interface Person { readonly id: number; // readonly Read-only name: string; age? : number; [propName: string]: any; } let pany: Person = { id: 1, name: 'pany', gender: 'male' }; pany.id = 2; // Compilation error: Cannot assign to 'id' because it is a constant or a read-only property.Copy the code
Note: The read-only constraint exists the first time an object is assigned, not the first time a read-only property is assigned
interface Person { readonly id: number; name: string; age? : number; [propName: string]: any; } let pany: Person = { name: 'pany', gender: 'male' }; pany.id = 2; // Error 1: id is not assigned to pany because it is read-onlyCopy the code
6. Array type
6.1 Representation of arrays
The simplest way is to use “type + square brackets” to represent arrays:
let fibonacci: number[] = [1, 1, 2, 3, 5];
Copy the code
But different types are not allowed:
let fibonacci: number[] = [1, '1', 2, 3, 5]; Type 'string' is not assignable to Type 'number'.Copy the code
You can also use the Array generic Array
to represent arrays:
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
Copy the code
Arrays can also be described as interfaces:
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
Copy the code
6.2 class array
Class arrays are not array types, such as arguments:
function sum() { let args: number[] = arguments; } // Error compilingCopy the code
Arguments is actually an array of classes and should not be represented as a normal array, instead it should be represented as an interface:
function sum() {
let args: {
[index: number]: number;
length: number;
callee: Function;
} = arguments;
}
Copy the code
In this example, in addition to restricting the type of the value to be a number when the index is of type number, we also restrict the length and callee attributes.
In fact, common class arrays have their own interface definitions, such as IArguments, NodeList, HTMLCollection, etc. :
function sum() {
let args: IArguments = arguments;
}
Copy the code
Where IArguments is the type defined in TS, which is essentially:
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
}
Copy the code
7. Type of function
7.1 Representation method of functions
Function declaration
function sum(x: number, y: number): number { return x + y; } // sum(1, 2) succeeded // sum(1, 2, 3) compiled error because arguments cannot be too many or too fewCopy the code
Functional expression
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
Copy the code
In the TS type definition, => is used to represent the function definition, with the input type on the left, which needs to be enclosed in parentheses, and the output type on the right. In ES6, => is called the arrow function.
Define function shapes with interfaces
interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { return source.search(subString) ! = = 1; }Copy the code
7.2 Optional Parameters
function buildName(firstName: string, lastName? : string) { if (lastName) { return firstName + ' ' + lastName; } else { return firstName; } } let tomcat = buildName('Tom', 'Cat'); let tom = buildName('Tom');Copy the code
Note: Optional parameters must be placed after required parameters; in other words, optional parameters are not allowed to be followed by required parameters
7.3 Default Values of Parameters
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
Copy the code
7.4 Remaining Parameters
With… Represents the remaining parameters, which are actually an array:
function push(array: any[], ... items: any[]) { items.forEach(function(item) { array.push(item); }); } let a: any[] = []; push(a, 1, 2, 3);Copy the code
Note: The remaining parameter can only be the last parameter
7.5 overloading
function reverse(x: number): number; function reverse(x: string): string; function reverse(x: number | string): number | string | void { if (typeof x === 'number') { return Number(x.toString().split('').reverse().join('')); } else if (typeof x === 'string') { return x.split('').reverse().join(''); }}Copy the code
Note: TS matches the first function definition first, so if multiple function definitions have inclusion relationships, write the exact definition first.
If this code surprises you, you’re right! Because I also think this writing method, more for “increase readability”……
Type assertion
8.1 grammar
The type used to manually specify a value. Syntax:
Value as typeCopy the code
or
< type > valueCopy the code
The second form cannot be used in TSX, and the syntax of <> is also used in “generics”, so the first syntax is generally used.
8.2 Assert a union type as one of the types
As mentioned earlier (4. Union type), when TS is not sure 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.
However, in cases where we really need to access a property or method specific to one of the types without determining the type, we need to assert:
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
function isFish(animal: Cat | Fish) {
if (typeof (animal as Fish).swim === 'function') {
return true;
}
return false;
}
Copy the code
Note: Type assertions can only “fool” the TS compiler and cannot avoid runtime errors, which can be caused by abusing type assertions.
8.3 Assert a parent class as a more concrete subclass
Assert a parent class as a more concrete subclass
There is a noteworthy conclusion in the article link above: the TS interface is a type, not a true value, and it will be removed from the compilation result, making it impossible to use Instanceof for runtime judgment.
8.4 Assert any type as any
Sometimes, we’re pretty sure this code won’t go wrong:
window.foo = 1;
Copy the code
But the compiler still tells us that foo does not exist on window.
This is where the assertion is needed:
(window as any).foo = 1;
Copy the code
It most likely hides a true type error, so don’t use as any unless you’re absolutely sure.
8.5 Assert any as a specific type
When you encounter a variable of type any, if you choose to ignore it, you will allow it to breed more any. Choose to improve it by asserting any as an exact type in a timely manner through type assertions, and move our code toward high maintainability.
Function getCacheData(key: string): any {return (window as any). Cache [key]; } // interface Cat {name: string; run(): void; } // declare any as type Cat const Tom = getCacheData(' Tom ') as Cat; tom.run();Copy the code
8.6 Limitations on type assertions
Restrictions on type assertions
ts.xcatliu.com
-
A union type can be asserted as one of these types
-
A parent class can be asserted as a subclass
-
Any type can be asserted to be any
-
Any can be asserted to any type
-
In order for A to be asserted as B, either A is compatible with B or B is compatible with A
In fact, the first four cases are special cases of the last one.
8.7 Double Assertion
Double assertion
Never use double assertion unless you absolutely have to.
8.8 Type Assertion vs type conversion
Type assertion vs type conversion
8.9 Type Assertion vs type declaration
Type assertion vs type declaration
Type declarations are more stringent than type assertions, so to increase the quality of the code, it is best to use type declarations in preference to the as syntax of type assertions.
8.10 Type Assertion vs generics
Type assertion vs generics
9. Declaration documents
When using a third-party library, you need to reference its declaration file to obtain the corresponding code completion, interface prompts and other functions.
Declaration file
10. Built-in objects
JS has many built-in objects that can be used directly as defined types in TS.
Built-in objects for 10.1 ES
// Boolean, Error, Date, RegExp etc. Let b: Boolean = new Boolean(1); let e: Error = new Error('Error occurred'); let d: Date = new Date(); let r: RegExp = /[a-z]/;Copy the code
10.2 Built-in objects for DOM and BOM
/ / Document, HTMLElement, Event, NodeList let allDiv: NodeList = Document. QuerySelectorAll (' div '); document.addEventListener('click', function(e: MouseEvent) { // Do something });Copy the code
10.3 TS core library definition file
TS actually does a lot of the typing work for you using some common methods:
Math.pow(10, '2'); // Error compilingCopy the code
Because math.pow must accept two number arguments, its type is defined as follows:
interface Math {
pow(x: number, y: number): number;
}
Copy the code
Here’s another example from DOM:
document.addEventListener('click', function(e) { console.log(e.targetCurrent); }); // Error compilingCopy the code
AddEventListener is defined in the TS core library as follows:
interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent { addEventListener(type: string, listener: (ev: MouseEvent) => any, useCapture? : boolean): void; }Copy the code
So e is inferred to be a MouseEvent, and MouseEvent has no targetCurrent attribute, so an error is reported.
Note: The TS core library definition does not include the Node.js section.
10.4 Writing A Node Using TS
Node.js is not part of the built-in object. If you want to write Node.js in TS, you need to import a third-party declaration file:
npm install @types/node --save-dev
Copy the code
Advanced article
TypeScript Introduction Notes (2)