I’ve been learning about TypeScript for a while now. Before I start learning about Vue3, I still need to know a little bit about TypeScript.
1. Meet the TypeScript
The introduction of TypeScript
TypeScript is an open source, cross-platform programming language developed by Microsoft. It is a superset of JavaScript that will eventually be compiled into JavaScript code.
Microsoft released the first public version of TypeScript in October 2012 and released TypeScript on June 19, 2013 after a preview release
TypeScript was written by anders hejlsberg, the chief architect of C#. It is an open source and cross-platform programming language.
TypeScript extends JavaScript’s syntax so that any existing JavaScript program can run in a TypeScript environment.
TypeScript is designed for large application development and can be compiled into JavaScript.
TypeScript is a superset of JavaScript that provides a type system and support for ES6+. It is developed by Microsoft and originated on GitHub
TypeScript is a superset of JavaScript that provides a type system and support for ES6+. It was developed by Microsoft and its code is opened on GitHub (new Window)
The characteristics of the TypeScript
TypeScript has three main features:
TypeScript compiles clean, concise JavaScript code, It can run in any browser, node.js environment, and any JavaScript engine that supports ECMAScript 3 (or later).
Powerful Type System The type system allows JavaScript developers to use efficient development tools and common operations such as static checking and code refactoring when developing JavaScript applications.
Advanced JavaScript TypeScript offers the latest and evolving JavaScript features, including those from ECMAScript 2015 and future proposals, such as asynchronous capabilities and Decorators, to help build robust components.
conclusion
TypeScript is becoming increasingly popular in the community, and it works well on large projects as well as base libraries, greatly improving our development efficiency and experience.
2. Install the TypeScript
Run the following command from the command line to install TypeScript globally:
npm install -g typescript
Copy the code
After the installation is complete, run the following command on the console to check whether the installation is successful (3.x) :
tsc -V
Copy the code
The first TypeScript program
Write TS programs
src/helloworld.ts
function greeter (person) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
Copy the code
Compiling code by hand
We use the.ts extension, but this code is just JavaScript.
On the command line, run the TypeScript compiler:
tsc helloworld.ts
Copy the code
The output is a helloworld.js file that contains the same JavsScript code as the input file.
On the command line, run this code from Node.js:
node helloworld.js
Copy the code
Console output:
Hello, Yee
Copy the code
Vscode automatically compiles
1). Generate the configuration file tsconfig.json
tsc --init
Copy the code
2). Modify tsconfig.json configuration
"outDir": "./js",
"strict": false,
Copy the code
3). Start monitoring task:
Terminal -> Run tasks -> Monitor tsconfig.jsonCopy the code
Type annotations
Let’s take a look at the advanced features that TypeScript tools bring. Add a string annotation to the argument to the person function as follows:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = 'Yee'
console.log(greeter(user))
Copy the code
Type annotations in TypeScript are a lightweight way to add constraints to functions or variables. In this example, we want the greeter function to take a string argument. Then try passing a call to greeter into an array:
function greeter (person: string) {
return 'Hello, ' + person
}
let user = [0, 1, 2]
console.log(greeter(user))
Copy the code
Recompile and you should see an error:
error TS2345: Argument of type ‘number[]’ is not assignable to parameter of type ‘string’. Similarly, try to remove all arguments to the greeter call. TypeScript tells you that the function was called with an unexpected number of arguments. In both cases, TypeScript provides static code analysis that examines the code structure and provides type annotations.
Note that the greeter.js file was created despite the error. Even if your code has errors, you can still use TypeScript. But in this case, TypeScript warns you that the code may not perform as expected.
interface
Let’s continue to extend the sample application. Here we use an interface to describe an object with firstName and lastName fields. In TypeScript, two types are compatible only if the structure inside them is compatible. This allows us to implement the interface without explicitly using the IMPLEMENTS statement, as long as we ensure that the required structure is included.
interface Person {
firstName: string
lastName: string
}
function greeter (person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName
}
let user = {
firstName: 'Yee',
lastName: 'Huang'
}
console.log(greeter(user))
Copy the code
class
Finally, let’s rewrite this example using classes. TypeScript supports new features of JavaScript, such as class-based object-oriented programming.
Let’s create a User class with a constructor and some public fields. Because the fields of the class contain the fields required by the interface, they are compatible.
Also note that I will specify all the member variables in the class declaration so that it is easy to see.
class User {
fullName: string
firstName: string
lastName: string
constructor (firstName: string, lastName: string) {
this.firstName = firstName
this.lastName = lastName
this.fullName = firstName + ' ' + lastName
}
}
interface Person {
firstName: string
lastName: string
}
function greeter (person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName
}
let user = new User('Yee', 'Huang')
console.log(greeter(user))
Copy the code
Re-run TSC Greeter. ts and you’ll see that the TypeScript class is just a syntactic sugar that is essentially an implementation of JavaScript functions.
conclusion
Now that you have a general idea of TypeScript, let’s take a look at some common TypeScript syntax in the next chapter.
4. Use Webpack to pack TS
-
Download dependencies (note that you should install dependencies in strict accordance with the following versions, older versions may cause problems)
Yarn add -d [email protected] yarn add -d [email protected] [email protected] yarn add -d [email protected] yarn Add -d [email protected] clean-webpack-plugin yarn add -d ts-loader yarn add -d cross-envCopy the code
-
JS: entrance SRC/main. Ts
// import './01_helloworld' document.write('Hello Webpack TS! ')Copy the code
-
Index page: public/index.html
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, <meta HTTP-equiv =" x-UA-compatible "content="ie=edge"> <title>webpack & TS</title> </head> <body> </body> </html>Copy the code
-
build/webpack.config.js
const {CleanWebpackPlugin} = require('clean-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') Const path = require('path') const isProd = process.env.node_env === 'production' return path.resolve(__dirname, '.. ', dir) } module.exports = { mode: isProd ? 'production' : 'development', entry: { app: './src/main.ts' }, output: { path: resolve('dist'), filename: '[name].[contenthash:8].js' }, module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader', include: [resolve('src')] } ] }, plugins: [ new CleanWebpackPlugin({ }), new HtmlWebpackPlugin({ template: './public/index.html' }) ], resolve: { extensions: ['.ts', '.tsx', '.js'] }, devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map', devServer: {host: 'localhost', // hostname stats: 'errors-only', // package log output output error message port: 8081, open: true},}Copy the code
Configuring packaging Commands
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
Copy the code
Run and package
yarn dev
yarn build
Copy the code
TypeScript common syntax
1. Basic types
TypeScript supports almost the same data types as JavaScript, and it also provides useful enumerated types for us to use.
- Boolean value
The most basic data types are simple true/false values, called Boolean in JavaScript and TypeScript (and in other languages as well).
let isDone: boolean = false;
isDone = true;
// isDone = 2 // error
Copy the code
- digital
Like JavaScript, all numbers in TypeScript are floating point numbers. These floating point numbers are of type number. In addition to supporting decimal and hexadecimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015.
Let a1: number = 10 // Decimal let a2: number = 0b1010 // binary let A3: number = 0o12 // octal let A4: number = 0xa // hexadecimalCopy the code
- string
Another basic operation of a JavaScript program is to process text data on the Web page or server side. As in other languages, we use string to represent the text data type. Like JavaScript, you can use double quotes (“) or single quotes (‘) to represent strings.
let name:string = 'tom' name = 'jack' // name = 12 // error let age:number = 12 const info = `My name is ${name}, I am ${age} years old! `Copy the code
- Undefined and null
In TypeScript, undefined and null have their own types called undefined and NULL, respectively. Their type by itself is not very useful:
let u: undefined = undefined
let n: null = null
Copy the code
By default null and undefined are subtypes of all types. This means that you can assign null and undefined to variables of type number.
- An array of
TypeScript manipulates array elements just like JavaScript. There are two ways to define an array. First, the element type can be followed by [] to represent an array of elements of that type:
let list1: number[] = [1, 2, 3]
Copy the code
The second way is to use Array generics, Array< element type > :
let list2: Array<number> = [1, 2, 3]
Copy the code
- Tuples Tuple
The tuple type allows you to represent an array with a known number and type of elements that need not be of the same type. For example, you can define a pair of tuples of type string and number.
let t1: [string, number]
t1 = ['hello', 10] // OK
t1 = [10, 'hello'] // Error
Copy the code
When accessing an element with a known index, we get the correct type:
Console. log(t1[0].substring(1)) // OK console.log(t1[1].substring(1)) // Error, 'number' does not exist 'substring' methodCopy the code
- The enumeration
Enum types complement the JavaScript standard data types. Enumeration types are used to give friendly names to a set of values.
Enum Color {Red, Green, Blue} enum Color {Red, Green, Blue} Color = Color.Green // 0 console.log(myColor, Color.Red, Color.Blue)Copy the code
By default, elements are numbered from 0. You can also manually specify the values of the members. For example, let’s change the above example to number from 1:
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green
Copy the code
Alternatively, all manual assignments are used:
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green
Copy the code
One of the conveniences provided by an enumerated type is that you can refer to its name by enumeration. For example, if we know that the value is 2, but are not sure which name in Color it maps to, we can look for the corresponding name:
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2]
console.log(colorName) // 'Green'
Copy the code
- any
Sometimes we want to specify a type for variables whose type is not known at programming time. These values may come from dynamic content, such as user input or third-party code libraries. In this case, we don’t want the type checker to check these values and just pass them through compile-time checks. We can then mark these variables with type any:
Let notSure: any = 4 notSure = 'maybe a string' notSure = false // Can be a BooleanCopy the code
The any type is useful when rewriting existing code, allowing you to optionally include or remove type checking at compile time. And the any type is also useful when you only know part of the data type. For example, you have an array that contains different types of data:
let list: any[] = [1, true, 'free']
list[1] = 100
Copy the code
- void
In a way, void is like the opposite of any; it means there is no type at all. When a function returns no value, you usually see the return type void:
*/ function fn(): */ function fn(): void { console.log('fn()') // return undefined // return null // return 1 // error }Copy the code
Declaring a void variable doesn’t do much good, because you can only assign undefined and null to it:
let unusable: void = undefined
Copy the code
- object
Object means a non-primitive type, that is, a type other than number, string, or Boolean.
Use the object type to better represent apis like Object.create. Such as:
function fn2(obj:object):object {
console.log('fn2()', obj)
return {}
// return undefined
// return null
}
console.log(fn2(new String('abc')))
// console.log(fn2('abc') // error
console.log(fn2(String))
Copy the code
- The joint type
Union Types indicate that the value can be one of many Types
-
Requirement 1: Define a string value for a function that returns a number or string value
function toString2(x: number | string) : string { return x.toString() }
-
Requirement 2: Define the length of a function to get a number or string value
function getLength(x: number | string) { // return x.length // error if (x.length) { // error return x.length } else { return x.toString().length } } Copy the code
- Types of assertions
Type assertions are a way of telling the compiler, “Trust me, I know what I’m doing.” Type assertion is like conversion in other languages, but without special data checking and deconstruction. It has no run-time impact, only at compile time. TypeScript assumes that you, the programmer, have done the necessary checks.
Type assertions come in two forms. One is the “Angle bracket” syntax and the other is the AS syntax
/* Type Assertion: Assertion can be used to manually specify a value Type: < Type > value Type 2: value as Type TSX only this way */ /* Requirements: */ function getLength(x: number | string) { if ((<string>x).length) { return (x as string).length } else { return x.toString().length } } console.log(getLength('abcd'), getLength(1234))Copy the code
- Type inference
Type inference: TS will infer a type when there is no explicit type: 1. 2. When a variable is defined, no value is assigned and the type is inferred to be any
// let b9 = 123 // number // b9 = 'ABC' // error / Let b10 // any b10 = 123 b10 = 'ABC'Copy the code
2. The interface
One of TypeScript’s core tenets is type-checking of the structure a value has. We use Interfaces to define the types of objects. An interface is an abstraction (description) of an object’s state (properties) and behavior (methods)
- Interface is a preliminary study
Requirement: create a person’s object that needs to constrain the person’s attributes
Id is number, must have, read-only name is string, must have age is number, must have sex is string, can not haveCopy the code
Here’s a simple example to see how the interface works:
/* In TypeScript, we use Interfaces to define the type of an object: Interfaces are abstractions of the object's state (properties) and behavior (methods). More or less objects of interface type are optional properties that are disallowed: Read-only property: readonly */ /* Requirements: Id is number, must have it, read-only name is string, must have age is number, must have sex is string, Interface IPerson {id: number name: string age: number sex: string} const person1: IPerson = {id: 1, name: 'Tom ', age: 20, sex:' male '}Copy the code
The type checker looks to see if the properties inside the object match the IPerson interface description, and if they don’t, it prompts a type error.
- Optional attribute
Not all attributes in the interface are required. Some exist only under certain conditions, or not at all.
interface IPerson { id: number name: string age: number sex? : string }Copy the code
An interface with optional attributes is similar to a normal interface definition, except that the optional attribute name definition is followed by one. Symbols.
One of the benefits of optional attributes is that you can pre-define possible attributes, and another is that you can catch errors when references to non-existent attributes.
Const person2: IPerson = {id: 1, name: 'Tom ', age: 20, // sex:' male '}Copy the code
- Read-only property
Some object properties can only change their value when the object is created. You can specify read-only properties with readonly before the property name:
interface IPerson { readonly id: number name: string age: number sex? : string }Copy the code
Once assigned, it cannot be changed.
Const person2: IPerson = {id: 2, name: 'Tom ', age: 20, // sex:' male '// 12 // error is not defined in the interface, cannot have} person2.id = 2 // errorCopy the code
- readonly vs const
The easiest way to determine whether to use readonly or const is to use it as a variable or as a property. Const as a variable, readonly as an attribute.
- Function types
Interfaces can describe the various shapes that objects in JavaScript can have. In addition to describing ordinary objects with attributes, interfaces can also describe function types.
To use the interface to represent function types, we need to define a call signature for the interface. It is like a function definition with only the argument list and return value types. Each parameter in the parameter list needs a name and type.
/* Interface SearchFunc {(source: string, subString: string): Boolean}Copy the code
With this definition, we can use this function type interface just like any other interface. The following example shows how to create a variable of function type and assign a function of the same type to it.
const mySearch: SearchFunc = function (source: string, sub: string): boolean {
return source.search(sub) > -1
}
console.log(mySearch('abcd', 'bc'))
Copy the code
- Class types
- Class implementation interface
Like C# or Java interfaces, TypeScript can use them to explicitly force a class to conform to a contract.
/* Class type: implement interface 1. A class can implement multiple interfaces 2. */ interface Alarm {alert(): any; } interface Light { lightOn(): void; lightOff(): void; } class Car implements Alarm { alert() { console.log('Car alert'); }}Copy the code
2. A class can implement multiple interfaces
class Car2 implements Alarm, Light { alert() { console.log('Car alert'); } lightOn() { console.log('Car light on'); } lightOff() { console.log('Car light off'); }}Copy the code
- Interface Inheritance interface
Like classes, interfaces can inherit from each other. This allows us to copy members from one interface to another, giving us more flexibility to split the interface into reusable modules.
interface LightableAlarm extends Alarm, Light {
}
Copy the code
Class 3.
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 ES6, 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.
- Basic example
Here is an example of using a class:
*/ class Greeter {// Declare the attribute message: string // constructor (message: String) {this.message = message} // Common method greet (): String {return 'Hello '+ this.message}} // Create an instance of the class const greeter = new Greeter('world') // call the method of the instance console.log(greeter.greet())Copy the code
If you’ve ever used C# or Java, you’ll be familiar with this syntax. We declare a Greeter class. This class has three members: a property called Message, a constructor, and a greet method.
You’ll notice that we use this when referring to any of the class members. It means that we are accessing a member of the class.
In the next line, we construct an instance of the Greeter class using new. It calls the previously defined constructor, creates a new object of Greeter type, and initializes it by executing the constructor.
The last line calls its greet method through the greeter object
- 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.
Look at the following example:
/* class Animal {run (distance: distance) number) { console.log(`Animal run ${distance}m`) } } class Dog extends Animal { cry () { console.log('wang! wang! ')}} const dog = new dog () dog.cry() dog.run(100) // Can call methods inherited from the parentCopy 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 cry() and run().
Now let’s look at a more complicated example.
class Animal { name: string constructor (name: string) { this.name = name } run (distance: number=0) { console.log(`${this.name} run ${distance}m`) } } class Snake extends Animal { constructor (name: String) {// call the parent constructor super(name)} // Override the parent type method run (distance: number=5) {console.log('sliding... ') super.run(distance) } } class Horse extends Animal { constructor (name: String) {// Calling the supertype constructor super(name)} // Overwriting the supertype method run (distance: number=50) {console.log('dashing... Super.run (distance)} XXX () {console.log(' XXX ()')}} const snake = new snake ('sn') snake.run() const Horse = new horse ('ho') horse.run() // Parent type references to instances of subtypes ==> polymorphic const Tom: Animal = new Horse('ho22') tom.run() Snake = new Animal('tom3') tom3.run() Horse = new Animal('tom2') // tom2.run()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.
This example demonstrates how a subclass can override a parent class’s methods. The Snake and Horse classes both create run methods that override the run method they inherited from Animal, so that the run method has different functions depending on the class. Note that even though Tom is declared Animal, because its value is Horse, when tom.run(34) is called, it calls the method overridden in Horse.
sliding...
sn run 5m
dashing...
ho run 50m
Copy the code
- Public, private, and protected modifiers
- The default for the public
In the example above, we can freely access the members defined in the program. If you’re familiar with classes in other languages, you’ll notice that we didn’t use the public modifier in the previous code; For example, C# requires that members be visible explicitly using public. In TypeScript, members default to public.
You can also explicitly mark a member as public. We can rewrite the Animal class as follows:
2. Understand the private
When a member is marked private, it cannot be accessed outside the class in which it is declared.
3. Understand the protected
Protected modifiers behave much like private modifiers, with one difference: protected members are still accessible in derived classes. Such as:
/* Access modifiers: used to describe the accessibility of attributes/methods within a class. Public: the default value. */ class Animal {public name: string public constructor (constructor) string) { this.name = name } public run (distance: number=0) { console.log(`${this.name} run ${distance}m`) } } class Person extends Animal { private age: Number = 18 protected sex: string = 'male' run (distance: number=5) {console.log('Person jumping... ') super.run(distance) } } class Student extends Person { run (distance: number=6) { console.log('Student jumping... ') console.log(this.sex) // Console.log (this.age) // Subclass cannot see the private super.run(distance)}} Console. log(new Person(' ABC ').name) // Public visible // console.log(new Person(' ABC ').sex) // Protected invisible // console.log(new Person(' ABC ').age) // Private invisibleCopy the code
- Readonly modifier
You can use the readonly keyword to make the property read-only. Read-only attributes must be initialized at declaration time or in a constructor.
class Person {
readonly name: string = 'abc'
constructor(name: string) {
this.name = name
}
}
let john = new Person('John')
// john.name = 'peter' // error
Copy the code
- Parameter properties
In the example above, we must define a read-only member name and a constructor that takes name in the Person class, and immediately assign the value of name to this.name, as is often the case. Parameter properties make it easy to define and initialize a member in one place. The following example is a modified version of the previous Person class, using the parameter attribute:
class Person2 {
constructor(readonly name: string) {
}
}
const p = new Person2('jack')
console.log(p.name)
Copy the code
Notice how we discard the name argument and use only the readonly name: string argument in the constructor to create and initialize the name member. We combine declaration and assignment in one place.
Parameter properties are declared by prefixing constructor arguments with an access qualifier. Using private to qualify a parameter property declares and initializes a private member; The same is true for public and protected.
- accessor
TypeScript supports intercepting access to object members via getters/setters. It helps you effectively control access to object members.
Here’s how to rewrite a simple class to use get and set. First, let’s start with an example that doesn’t use accessors.
class Person {
firstName: string = 'A'
lastName: string = 'B'
get fullName () {
return this.firstName + '-' + this.lastName
}
set fullName (value) {
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
const p = new Person()
console.log(p.fullName)
p.firstName = 'C'
p.lastName = 'D'
console.log(p.fullName)
p.fullName = 'E-F'
console.log(p.firstName, p.lastName)
Copy the code
- Static attributes
So far, we’ve only talked about instance members of a class, attributes that are initialized only when the class is instantiated. We can also create static members of a class whose properties exist on the class itself rather than on an instance of the class. In this example, we define Origin as static because it is the property used by all grids. Every instance that wants to access this property must prefix origin with the class name. Just as we used this. XXX on instance properties to access properties, here we use grid.xxx to access static properties.
/* class Person {name1: string = 'A' static name2: string = 'B' } console.log(Person.name2) console.log(new Person().name1)Copy the code
- An abstract class
Abstract classes are used as base classes for other derived classes. They cannot be instantiated. Unlike interfaces, abstract classes can contain implementation details of members. The abstract keyword is used to define abstract classes and abstract methods within abstract classes.
/* An abstract class cannot create instance objects. Only implementation classes can create instances that contain unimplemented abstract methods */ abstract class Animal {abstract cry () run() {console.log('run()')}} class Dog extends Animal { cry () { console.log(' Dog cry()') } } const dog = new Dog() dog.cry() dog.run()Copy the code
4. The function
Functions are the foundation of JavaScript applications, helping 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.
- Basic example
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.
The following is a quick reminder of both JavaScript functions:
Let myAdd = function(x, y) {return x + y; }Copy the code
- Function types
- Define a type for a function
Let’s add a type for the above function:
function add(x: number, y: number): number {
return x + y
}
let myAdd = function(x: number, y: number): number {
return x + y
}
Copy the code
We can add a type for each parameter and then add a return type for the function itself. TypeScript can automatically infer return value types from return statements.
- Write the full function type
Now that we have specified the type for the function, let’s write out the full type of the function.
let myAdd2: (x: number, y: number) => number =
function(x: number, y: number): number {
return x + y
}
Copy the code
- Optional and default parameters
Every function argument in TypeScript is required. This does not mean that null or undefined cannot be passed as an argument, but rather that the compiler checks whether the user has passed in a value for each argument. The compiler also assumes that only these arguments are passed into the function. In short, the number of arguments passed to a function must be the same as the number of arguments expected by the function.
In JavaScript, each parameter is optional and can be passed or not. When no parameter is passed, its value is undefined. In TypeScript we can use it next to parameter names, right? Realize the function of optional parameters. For example, we want lastName to be optional:
In TypeScript, we can also provide a default value for a parameter when the user does not pass the parameter or when the value passed is undefined. They are called parameters with default initialization values. Let’s change the example above and set firstName to “A” by default.
function buildName(firstName: string='A', lastName? : string): string { if (lastName) { return firstName + '-' + lastName } else { return firstName } } console.log(buildName('C', 'D')) console.log(buildName('C')) console.log(buildName())Copy the code
The remaining parameters
Required, default, and optional parameters have one thing in common: they represent a parameter. Sometimes, you want to manipulate multiple arguments at once, or you don’t know how many arguments will be passed in. In JavaScript, you can use arguments to access all incoming arguments.
In TypeScript, you can collect all arguments into a single variable: the remaining arguments are treated as an unlimited number of optional arguments. You could have none, you could have any of them. The compiler creates an array of parameters named after the ellipsis (…) you use. Given a name later, you can use this array inside the body of a function.
function info(x: string, ... args: string[]) { console.log(x, args) } info('abc', 'c', 'b', 'a')Copy the code
- Function overloading
Function overloading: In JS, there is no such thing as function overloading due to weak typing and parameter participation. However, in TS, and other object-oriented languages (such as Java), this syntax exists
*/ * function add (x: x); /* function add (x: x); String, y: string) : string function to the add (x: number, y: number) : the number / / define functions to realize the function add (x: string | number, y: string | number): String | number {/ / we should pay attention to in implementing strict judge whether the type of the two parameters are equal, If (typeof x === 'string' && typeof y === 'string') {return x + y} else if (typeof x === 'number' && typeof y === 'number') { return x + y } } console.log(add(1, 2)) console.log(add('a', 'b')) // console.log(add(1, 'a')) // errorCopy the code
5. The generic
A feature that does not specify a specific type when defining a function, interface, or class, but specifies the specific type when it is used.
- The introduction of
Create an array of count values based on the specified number count and data value. Without generics, this function might look like this:
function createArray(value: any, count: number): any[] {
const arr: any[] = []
for (let index = 0; index < count; index++) {
arr.push(value)
}
return arr
}
const arr1 = createArray(11, 3)
const arr2 = createArray('aa', 3)
console.log(arr1[0].toFixed(), arr2[0].split(''))
Copy the code
-
Use function generics
function createArray2 <T> (value: T, count: number) { const arr: Array<T> = [] for (let index = 0; index < count; index++) { arr.push(value) } return arr } const arr3 = createArray2<number>(11, 3) console.log(arr3[0].toFixed()) // console.log(arr3[0].split('')) // error const arr4 = createArray2<string>('aa', 3) console.log(arr4[0].split('')) // console.log(arr4[0].toFixed()) // error Copy the code
-
A function with multiple generic parameters
A function can define more than one generic parameter
function swap <K, V> (a: K, b: V): [K, V] {
return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())
Copy the code
- A generic interface
When you define an interface, you define generic types for properties or methods in the interface. When you use the interface, you specify specific generic types
interface IbaseCRUD <T> { data: T[] add: (t: T) => void getById: (id: number) => T } class User { id? : number; //id Primary key autoincrement name: string; // name age: number; Constructor (name, age) {this.name = name this.age = name}} class UserCRUD implements IbaseCRUD <User> {data: User[] = [] add(user: User): void { user = {... User, id: date.now ()} this.data.push(user) console.log(' save user', user.id)} getById(id: number): User { return this.data.find(item => item.id===id) } } const userCRUD = new UserCRUD() userCRUD.add(new User('tom', 12)) userCRUD.add(new User('tom2', 13)) console.log(userCRUD.data)Copy the code
- A generic class
When you define a class, you define generic types for properties or methods in the class. When you create instances of the class, you specify specific generic types
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
}
let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) {
return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))
Copy the code
- Generic constraint
If we take the length property of a generic argument, we get an error because the generic doesn’t know it has the length property
Function fn <T>(x: T): void {// console.log(x.length) // error}Copy the code
We can do this using generic constraints
interface Lengthwise { length: number; } function fn2 <T extends Lengthwise>(x: T): void {console.log(x.length)}Copy the code
We need to pass a value that matches the constraint type, which must contain the must Length attribute:
Fn2 (' ABC ') // fn2(123) // Error number has no length attributeCopy the code
6. Other
- Declaration file
When using a third-party library, we need to reference its declaration file to get the corresponding code completion, interface prompts and other functions
What is a declaration statement
If we want to use the third-party library jQuery, a common way to do this is in HTML
But in TS, the compiler doesn’t know what $or jQuery is
/* When using a third-party library, we need to reference its declaration file to get the corresponding code completion, interface hints, etc. Declare var jQuery: (selector: string) => any; declare var jQuery: (selector: string) => any; NPM install @types/ jQuery --save-dev */ jQuery('#foo'); // ERROR: Cannot find name 'jQuery'.Copy the code
At this point, we need to declare var to define its type
declare var jQuery: (selector: string) => any;
jQuery('#foo');
Copy the code
Declare var does not really define a variable, it just defines the type of the global variable jQuery, which is only used for compile-time checks and will be deleted in the compile result. It compiles as follows:
jQuery('#foo');
Copy the code
The declaration file is usually written as a separate XXX.D. TS file
Create 01_jquery.d.ts and define the declaration statement. The TS compiler will scan and load all the TS declaration files in the project
declare var jQuery: (selector: string) => any;
Copy the code
Many third party libraries are defined the corresponding declaration documents, library file name is commonly @ types/XXX, can be in www.npmjs.com/package/pac… To search
Some third libraries automatically download the corresponding declaration file library (e.g. Webpack) while others may need to download it separately (e.g. JQuery/React).
- Built-in objects
There are many built-in objects in JavaScript that can be treated directly as defined types in TypeScript.
Built-in objects are objects that exist in the Global scope according to the standard. Standards here refer to ECMAScript and standards in other environments such as DOM.
ECMAScript built-in object
Boolean Number String Date RegExp Error
/* 1. ECMAScript built-in object */ let b: Boolean = new Boolean(1) let n: Number = new Number(true) String = new String('abc') let d: Date = new Date() let r: RegExp = /^1/ let e: Error = new Error('error message') b = true // let bb: boolean = new Boolean(2) // errorCopy the code
BOM and DOM built-in objects
Window Document HTMLElement DocumentFragment Event NodeList
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()
Copy the code
Ok, today first share this, the next article is Vue3 related content! Interested partners support support!