What is TypeScript?

TypeScript is a free and open source programming language developed by Microsoft. It is a superset of JavaScript, and essentially adds optional static typing and class-based object-oriented programming to the language. An online TypeScript walkthrough

1.1 TypeScript is different from javascript

1.2 JavaScript data types

String Number Boolean Object (Array, Function) Symbol undefined null

1.3 New TypeScript data types

Void, any, never, tuple, enumeration, advanced types

2. Basic types

String type

We use string to represent the text data type. Like JavaScript, you can use double quotes “or single quotes” for strings, and backquotes to define multiple lines of text and inline expressions.

let str: string = 'abc'
Copy the code

Numeric types

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 a: number = 6 // Decimal let hexA: number = 0xf00D // Hexadecimal let binaryA: number = 0b1010 // Binary let octalA: Number = 0o744 // octalCopy the code

Boolean type

We use Boolean to represent Boolean types, representing logical values true/false.

let bool: boolean = true
Copy the code

Null & Undefined

Null indicates that an object value is missing, and undefined indicates an undefined value.

let un: undefined = undefined
let nu: null = null
Copy the code

void

Used to identify the type of value returned by a method, indicating that the method has no return value.

function noReturn (): void {
  console.log('No return value')
}
const a =():void=>{console.log('No return value')}
Copy the code
  • Undefined is not a reserved field that can be assigned, so it is recommended to use void 0 when setting undefined

Any type

A variable declared as any can be assigned a value of any type.

let x: any
x = 1
x = 'a'
x = {}

let arr: any[] = [1, 'a', null]
Copy the code

never

The never type represents the types of values that never exist. For example, the never type is the return type of function expressions or arrow function expressions that always throw an exception or have no return value at all; Variables can also be of type never, when they are bound by type protection that is never true.

The never type is a subtype of any type and can be assigned to any type; However, no type is a subtype of never or can be assigned to a type of never (except never itself). Even any cannot be assigned to never.

Function error(message: string): never {throw new error(message); }Copy the code
  • Type inference: Variables are declared without a value, and type inference isany

If other types need to be assigned null or undefined, set scriptNullChecks to false in tsconfig.json. Or use union types.

Symbol

Values of type symbol are created through the Symbol constructor

let s: symbol = Symbol()
Copy the code

Complex types

An array ofarray

There are two ways to define arrays. First, you can add [] to the element type. Second, you can use the Array generic Array< element type >. In addition, you can use union types in element types. | say or symbols.

let arr1: number[] = [1, 2, 3] let arr2: Array<number> = [1, 2, 3] let arr3: Array < number | string > = [1, 2, 3, 'a'] / / Array elements must be fixed type, Let a:number[] = [1,2,3,'4'] // error '4'string is not numberCopy the code

tuplestuple

An array representing the number and type of known elements. The elements need not be of the same type, but must be of the same type at their corresponding positions.

let tuple:[string,number] = ['ali',18]
Copy the code

You can call the array push method to add elements, but you can’t read the newly added elements.

tuple.push('a')
console.log(tuple) // ['ali',18, "a"]
tuple[2] // Error: Tuple type '[number, string]' of length '2' has no element at index '2'.
Copy the code

objectobject

Let a: object; Doesn’t it make sense because there are too many objects in JS

We can use it this way

let obj:{age:number,is:boolean};
obj = {
    age:18,
    is:true,
}
Copy the code

Attributes must be of type {name: string; age: number; }

functionfuntion

We need to specify the input and return types of the function

Inside is the type of the input parameter

=> indicates the type of the returned value

The following are all declaration types, and have nothing to do with the code logic

An error is reported if you pass extra arguments. Note: The optional parameter cannot be added

Function sum(a:number,b:number,c? :number):number{ return a+b; } // const sum = (a:number,b:number):number=>a+b console.log(sum(1,2,3))Copy the code

Use interfaces to describe function types

Note that => was used earlier to indicate the return value type

Here is the return value type after ()

interface Isum{
    (a:number,b:number):number;
}

const newSum:Isum = sum
Copy the code

interfaceinterface

It is very convenient to help us define Ojbect types, can be flexible to handle multiple types of attributes and whether mandatory/optional/read-only

In the interface property, right? Said not necessary properties | said joint types: sure what is available after several types the readonly immutable, cannot be modified after the definition, with const is a bit like, but is const variable, readonly for attributes

Interface Iobj {a:string | number; Readonly age:number; love? :string; } let obj:Iobj = { a:'jom', age:18, } obj.age = 30 //Cannot assign to 'age' because it is a read-only propertyCopy the code

The joint typeunion types

For the type of a variable may be we can use any of several types, but any range is a bit big, to avoid as far as possible, if we knew which is one of the several types, we can use the joint type With | note: Only common methods and attributes can be accessed before assignment, as in the following example where number has no length attribute

let a:number|string;

a.length //Property 'length' does not exist on type 'string | number'.\
           Property 'length' does not exist on type 'number'

a='haha';
a=1;
Copy the code

assertionstype inference

In the above example, we declare a property type to number | string it cannot call length method It is machine can not determine the type, but we can specify the type string here we can use the assertion type assertion comes in two forms: < type >, the as

function sum(a:number|string):void{
  const str = a as string  //as
  const str = <string>a    //<>
  console.log(str.length) 
}
Copy the code

The two forms are equivalent. But when you use JSX in TypeScript, only AS syntax assertions are allowed.

Type the guardstype guard

When dealing with federated types, use type guards to narrow the scope

Implement the same method as above

function sum(a:number|string):void{
    if(typeof a ==='string'){
        console.log(a.length) 
    }
}
Copy the code

In addition to typeof, there are instanceof and in type guards

4, the enumeration

We use enum for enumeration types. Enumeration member values are read-only and cannot be modified. This is generally used to declare a constant

Digital enumeration

Digital enumerations support reverse mapping

The initial value is 0 and increases gradually. You can also customize the initial value and then increase gradually based on the initial value.

enum fiveLamp {
    white,
    red,
}
console.log(fiveLamp.white) // 0
console.log(fiveLamp[1]) // 'red'
console.log(five)//{ "0": "white", "1": "red", "white": 0, "red": 1 }
Copy the code

String enumeration

String enumerations do not support reverse mapping

Enum Message {Success = 'Success ', Fail =' failure '}Copy the code

Constant enumeration

Add const before the enumeration keyword. The constant enumeration is removed at compile time.

const enum Month {
  Jan,
  Feb,
  Mar
}
let month = [Month.Jan, Month.Feb, Month.Mar]
Copy the code

The compiled:

"use strict";
var month = [0 /* Jan */, 1 /* Feb */, 2 /* Mar */]; // [0 /* Jan */, 1 /* Feb */, 2 /* Mar */]
Copy the code

External enumeration

External enumeration (Ambient Enums) is an enumeration type defined using declare Enum.

declare enum Month {
  Jan,
  Feb,
  Mar
}
let month = [Month.Jan, Month.Feb, Month.Mar]
Copy the code

The compiled:

"use strict";
let month = [Month.Jan, Month.Feb, Month.Mar];
Copy the code

The type defined by DECLARE will only be used for compile-time checks and will be removed from the compilation result. So, according to the compiled results of the above example, it is clearly not possible. Because Month is undefined.

  • declareconstCan coexist

5, class,

In ES6 we already have the concept of classes, adding some functionality to classes in TS. Here is a simple example that defines a Parent class and a Child class

Three access modifiers:

Public: Decorated properties or methods that are common and accessible anywhere

Private: Modified properties or methods are Private and accessible only in the class

Protected: Modified properties or methods are Protected and accessible in the class and subclasses

For example, if you specify that age is private in the Parent class and can only be accessed in the Parent class, the child class will fail

class Parent { public name:string private age:number constructor(name:string){ this.name = name } play(){ Console. log(' ${this.name} ')}} Class Child extends Parent{private child_age:number constructor(name:string){ super(name) this.child_age = super.age; Property 'age' is private and only accessible within class 'Parent'.}}Copy the code

We can make access protected so that subclasses can access it

Static attribute static

The name age properties above are both accessed by instance

Properties decorated static are accessed through classes and are common to each instance

In the same way that static can modify methods, methods that are modified with static are called class methods and can be called directly with the class

class Parent {
    static name:string
}
console.log(Parent.name)
Copy the code

Read-only readonly

Adding readOnly to the property ensures that it is read-only and cannot be modified. If there is a static modifier, write it after it

Class Parent {static readonly name:string =' hahaha'} Parent. Name =' hahaha hahaha' //Cannot assign to 'name' because it is a read-only property.Copy the code

An abstract class abstract

Abstract classes added by TS cannot be instantiated and can only be inherited if they are created using the class directly (cannot be new)

Add the abstract modifier before class,

Abstract methods can be written in abstract classes, which have no method body

For example: an abstract class of an animal, there is a method called, not every animal sounds the same, we can set it to abstract method, concrete function subclass implementation (the name of the class is written by the subclass).

abstract class Animal { public name:string constructor(name:string){ this.name = name } abstract barking():void } class Cat extends Animal{constructor(name:string){super(name)} Barking (){console.log(' meow ~ ')}}Copy the code

6. Interfaces inherit interfaces

  • Like class inheritance class, the same object can inevitably be inherited, interface can also inherit interface, connection mode is also usedextends.
Interface addIce{ice:string} interface addSugar extends addIce{sugar:string} let milk: {ice:string} Sugar :' half sugar '}Copy the code
  • The two interfaces defined in the above example areaddIce addSugarAnd theaddSugarinheritedaddIcetheiceProperty, so in useaddSugarInterfaces must have the same shape.
  • inmilkVariable because it is usedaddSugarInterface, so an error is reported if the property does not conform to the shape.

Interface inheritance class

  • inTypeScriptWe can use interfaces to inherit classes.
Class constructor {ice:string sugar:string constructor(ice:string,sugar:string){// Constructor is a constructor that receives the parameter this.ice = ice;  this.sugar = sugar; }; } interface doSthing extends MilkTea{} let milk:doSthing={ice:' doSthing ', sugar:' doSthing '}Copy the code
  • In the above example, our interface defines the shape, and the shape itself has nothing, but it inherits the ice and sugar properties of the MilkTea class, so we specify that the variables using this interface must have ice and sugar properties.

  • As shown above, milk gives it a doSthing interface, so this variable needs to have ice and sugar attributes.

  • Interfaces and classes are not the same thing so how can they be inherited? They’re not the same thing, but when we define a class, we’re defining a type.

  • For example, when we create this class, we also create a type of MilkTea, which we can use in this way.

Class constructor {ice:string sugar:string constructor(ice:string,sugar:string){// Constructor is a constructor that receives the parameter this.ice = ice;  this.sugar = sugar; }; } let milk:MilkTea={ice:' less ice ', sugar:' half sugar '}Copy the code
  • There is no problem with this, so when we inherit the doSthing interface, we actually integrate the type MilkTea, which is familiar to everyone. It is written in the same way as interface, so we inherit a class, in fact, we inherit an interface.

  • It is worth noting that when an interface inherits a class, it inherits only its instance properties and methods, not its constructors.

8 and generic

A generic type is like a placeholder for a variable, and when used we can pass in the defined type as a parameter and output it as if it were a parameter

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, so it can be done as follows: where T is equivalent to a placeholder in the method (variable, interface….) Etc.) followed by

function identity<T>(arg: T): T{
    return arg; 
}
Copy the code

Multiple parameters are similarly written

function identity<T,U>(arg:[T,U]):[T,U]{ return arg; } // Select 'T ',' U 'identity(['1',1]);Copy the code

You can also use interfaces to constrain generics

The extends Ilen extends after T, which defines the code in Ilen to say that T must have a length property

This will not result in an error when params.length is called from within the method

interface Ilen{ length:number; } function getLenght<T extends Ilen>(params:T):number{ return params.length } getLenght('sffsdf'); getLenght(11); Argument of type 'number' is not assignable to parameter of type 'Ilen'Copy the code

Use generics in classes

Class Cat<T>{eat(name:T){console.log(' this Cat ate '+name)}} let newCat = newCat <string>() newcat.eat (' rat ') / / error newCat. Eat (111)Copy the code

Use generics in interfaces

interface Iobj<T,U>{
  key:T
  value:U
}

const a:Iobj<string,number> = {key:'admin',value:1}
const b:Iobj<string,boolean> = {key:'admin',value:false}
Copy the code

Type aliasestype

type a  = string|number
let b:a  = 11
Copy the code

10. Cross types&

To combine the types, variable assignments must satisfy the cross type

interface Iobj{
  key:number;
}

type newObj  = Iobj&{value:string}

let a:newObj  = {key:1,value:'hhh'}
Copy the code