Why do I say these words without forgetting/What brand of arrow did you stab my heart with

I’ve been in the war/in the army/still/wounded by an arrow

— Li Ronghao, “Read and Remember”

I’ll introduce TypeScript in the next two articles.

I am also a beginner to TypeScript, and these two articles are my study notes from a series of free videos that are good, if you want to learn faster, you can see them here.

What’s the difference between TypeScript and JavaScript? To put it simply, the former introduces type constraint, can realize static code inspection, and can provide more perfect code prompt function; In addition, the introduction of interfaces, abstract classes, enumerations, access control modifiers, generics and other syntax makes our code more robust and extensible.

The contents of the first and the next two articles are arranged as follows:

  • “The last”
    1. Basic types of
    2. Object type
    3. Extension type
  • “Next”
    1. Object-oriented programming
    2. The generic

The first part is defined as the basic part, and the second part is defined as the in-depth part.

Let’s start with the basics.

The development environment

TypeScript scripts end with the.ts suffix. I use VSCode to learn about TypeScript. Once I write TypeScript code, I need to compile it into JavaScript code to run. To do this, we need to install the Node.js environment.

Then install the TypeScript compilation environment.

$ npm install -g typescript
$ tsc --version
Copy the code

The instructions for compiling the file are as follows:

// After executing the following statement, you will see a 'helloworld.js' file in the same directory$ tsc HelloWorld.ts
Copy the code

Codepen. IO also supports TypeScript writing. When you create a new Pen, set the JavaScript preprocessor to TypeScript, and you can see the compiled code in real time, but it’s not very informative.

Basic types of

Let’s start with the simplest Primitive data type (Primitive).

ECMAScript provides six basic data types: Boolean, numeric, string, Null, Undefined, and Symbol.

TypeScript provides typeliterals for each of these types: Boolean, number, string, NULL, undefiend, and symbol (introduced in ES6, but not symbol in this series).

In TypeScript, variables are typed using the: type syntax:

// Declare a Boolean type variable 'isMale' with an initial value of 'true'
let isMale: boolean = true;
// Declare a string variable 'myName' with an initial value of 'Alex'
let myName: string = 'Alex';
// Declare a numeric type variable 'myAge' with an initial value of '20'
let myAge: number = 20;
// Declare a Null variable 'myGirlFriend' with a value of 'Null'
let myGirlFriend: null = null;
// Declare a variable of Undefined type 'myHouse' with the value 'Undefined'
let myHouse: undefined = undefined;
Copy the code

Note: TypeScript provides all type literals in lower case, which is distinguished from uppercase, which is a JavaScript natively provided constructor function.

Sometimes there is more than one type of a variable. For example, the value of a variable can be either a string or a number. This is where the “union type” comes in.

Joint type using the vertical bar | space, say any one type of a variable can give value.

In the following example, we declare a variable foo, which can be a string or a number.

// Declare a variable 'foo', which can be either a string or a number
let foo: string | number = 'bar'; // The initial value is given to the string 'bar'
foo = 123; // Then reassign 'foo' to '123'
Copy the code

Object type

After basic types, objects are the most common thing you work with. So how do you specify object types in TypeScript?

Define the object

In TypeScript, the interface keyword is used to describe the shape, or type, of an object. In traditional object-oriented programming languages such as Java, “interface” stands for “behavior abstraction.” TypeScript does this a little differently. Interfaces not only represent behavior abstraction, but also define object types.

Next, we define a type Person (capitalized by convention) :

// Declare a type 'Person' with the interface
interface Person {
    name: string;
    age: number;
}

// Declare the variable 'Alex' as type 'Person'
let alex: Person = {
    name: 'Alex',
    age: 20
};
Copy the code

Note: When defining interfaces, you can use semicolons between attributes; , can be separated by commas, or even nothing at all.

We define a type Person and declare the type of the variable Alex as Person. The assignment object must consist of a string attribute name and a numeric attribute age. Any missing or extra attributes will be given an error.

// Error message (missing an attribute)
let alex: Person = {
    name: 'Alex';
};

// Error (extra attribute)
let alex: Person = {
    name: 'Alex',
    age: 20,
    gender: 'male'
};
Copy the code

When defining a type, if you want to indicate that an attribute is optional, use? : type Indicates a syntax statement.

// The 'name' attribute of type 'Person' is optional
interface Person {
    name: string; age? :number;
}

// Since 'age' is an optional attribute, it is ok not to assign it
let alex: Person = {
    name: 'Alex'
};
Copy the code

In addition to defining optional properties, you can also define “arbitrary properties.”

The so-called arbitrary attribute is that we are not sure what the name of the attribute will be added in the future, but we will define the allowed attribute in advance, and limit the type of the attribute in the case of uncertain future name of the attribute.

// an arbitrary attribute is defined in Person. The attribute type is' any 'interface Person {name: string; age? : number; [propName: string]: any; } // We add an arbitrary attribute to 'alex'. 'gender' let Alex: Person = {name: 'Alex', gender: 'male};Copy the code

We define an arbitrary property of type any using the form [propName: String]: any.

Note that the type of any attribute must be a superset of the name and age types of the known attributes above, otherwise an error will be prompted. For example, the above we can amend the above any property of any type to string | number may be used.

After objects, let’s talk about arrays.

An array type

Specifying a type on an array essentially limits the types of array members. In TypeScript, the type[] syntax is used to specify the types of array members.

The following defines an array that restricts its members to strings.

// We define an array 'myFriends' whose members are restricted to strings
let myFriends: string[] = ['Alex'.'Bob'];
Copy the code

If the type of the array members allowed to contain multiple values, use (type1 | type2 |…). [] syntax declaration.

// We define an array 'foo' whose members can be strings or numbers
let foo: (string | number) [] = ['Alex'.'Bob'.123];
Copy the code

If the members of an array are objects, they can be declared in one of two ways:

// Method 1: Declare 'friends' member types through predefined types
interface Person {
    name: string;
}
let friends: Person[] = [ { name: 'Alex' }, { name: 'Bob'}];// Method 2: Declare 'friends' member types directly as literal types
let friends: {
    name: string
}[] = [ { name: 'Alex' }, { name: 'Bob'}];Copy the code

Next, move on to the study of extension types.

Extension type

In addition to supporting JavaScript types, Typescript provides several extension types.

First, let’s talk about literal types.

Literal type

When we assign as follows:

let seven: number = 7;
// ❌ : 'Type '"Seven"' is not assignable to Type 'number'
seven = 'Seven';
Copy the code

Note that ‘Seven’ is treated as a type, saying that the ‘Seven’ type cannot be assigned to the numeric type variable Seven.

‘Seven’ is a string literal type.

Typescript literals include string literals, numeric literals, and Boolean literals.

In addition, we can define a new type using the type keyword:

// Here we define a new type 'FavoriteNumber'. This new type consists of only a set of three values
type FavoriteNumber = 'One' | 'Two' | 'Seven';
// Next, declare the variable 'seven' as type 'FavoriteNumber' and assign it to 'seven'
let seven: FavoriteNumber = 'Seven';
Copy the code

The above defines a type FavoriteNumber, which consists of a set of three values (a type usually contains at least two or more values). The variable seven is declared as this type and assigned to ‘seven’, which is a valid value. If we assign seven a value outside the FavoriteNumber type, an error is reported, such as:

// ❌ 'Type '123' is not assignable to Type 'FavoriteNumber'.
let seven: FavoriteNumber = 123;
Copy the code

The enumeration

Before we get to enumeration types, let’s look at the following code:

// Two variables' errorColor 'and' infoColor 'are defined here
let dangerColor = 'red';
let infoColor = 'blue';

// Add a function to determine if the incoming color is a dangerous color
function isItDangerColor(color) {
    return color === 'red';
}

// Next, call function 'isItRed'
isItDangerColor(dangerColor); // true
isItDangerColor(infoColor); // false
Copy the code

The logic of this little piece of code is simple, but there is a small problem — if the danger color changes from ‘red’ to ‘pink’, then we need to change the code in two places.

To solve this problem, we modify the code slightly by introducing a variable Colors that represents a collection of Colors:

// We use the variable 'Colors' to store the set of Colors used in the logic
const Colors = {
    Danger: 'red',
    Info: 'blue'
};

// In the rest of the business logic, we use the color variable instead of the previous color literal
let dangerColor = Colors.Danger;
let infoColor = Colors.Info;

function isItDangerColor(color) {
    return color === Colors.Danger;
}
Copy the code

The convenience of this is that if the color value represented by colors. Danger changes, you can simply modify it in Colors.

On further reflection, it doesn’t matter what the values of colors. Danger and colors.info are, as long as they’re not equal to each other. For example, let’s write it like this:

// This definition of 'Colors' still does not affect the logic
const Colors = {
    Danger: 0,
    Info: 1
};
Copy the code

This way of defining variables, overwritten with TypeScript enumerations, looks like this:

// Enumeration variables are defined using the 'enum' keyword
// An enumeration variable 'Colors' is defined here
enum Colors {
    Danger,
    Info
}
Copy the code

After compiling the above code, the resulting JavaScript source code is as follows:

var Colors;
(function (Colors) {
  Colors[Colors["Danger"] = 0] = "Danger";
  Colors[Colors["Info"] = 1] = "Info";
})(Colors || (Colors = {}));
Copy the code

It follows that,

enum Colors {
    Danger,
    Info
}

/ / equivalent to the

var Colors = {
    0: 'Danger'.1: 'Info'.'Danger': 0.'Info': 1
};
Copy the code

Let’s modify the original example to use enumerations to organize logic:

enum Colors {
    Danger, // The corresponding value is 0
    Info, // The corresponding value is 1
    Success // The corresponding value is 2
}

// We constrain the color of function 'isItDanger' to 'Colors'
// Indicates that this function accepts only the values listed in 'Colors'
function isItDanger(color: Colors) :boolean {
    return color === Colors.Danger;
}

// Then call the 'isItDanger' function with 'colors.info'
isItDanger(Colors.Info); // false
Copy the code

In addition to using the default index value, we can also specify a value for each item in the enumeration variable:

enum Colors {
    Red, // The corresponding value is 0
    Blue = 3.// 将 Blue 值指定为 3
    Green // connect to 3, where value is 4
}

enum Colors {
    Red = 'red'.// The corresponding value is 'red'
    Blue = 'blue'.// The corresponding value is 'blue'
    Green = 'green' // The corresponding value is 'green'
}
Copy the code

Finish last.