TypeScript learning notes

TypeScript learning notes

TypeScript overview and environment

TypeScript (TS for short) is a superset of JavaScript (both JS and TS).

TypeScript = Type + JavaScript (added type system for JS)

Install the toolkit typescript for parsing TS

Installation steps:

  1. Open the VSCode terminal.

  2. Enter the installation command: npm i -g typescript, press enter to install (Note: networking is required).

typescript: a toolkit for parsing ts. tsc command is provided to realize the transformation of TS - > JS.
npm: used to install packages used in front-end development. It is used to install node JS is installed automatically.
i (install): indicates installation.
-g (– global): Global ID, which can be used in any directory.

  1. Installation view: tsc -v / tsc --version

Install the TS node toolkit to simplify TS execution

  • In this toolkit, the tsc command will be used to convert TS files into JS files
  • The command TS node is used internally to execute the generated JS code.

Installation command: NPM I - G TS node

Usage: TS node hello ts

  • In the later stage, it will not be so troublesome to use ts in the scaffold. This method is temporarily used for beginners of grammar

Entry code

Create hello TS file, console log(“hello TS”)

Execute on the terminal: TSC hello ts

Will generate a hello JS file

Notes in TS

// Single line

/* Multiline */

JS original type

  • After the data type is limited, the subsequent assignment must conform to the attribute type, otherwise the compilation will report an error!
  • If the initial letter of the basic type is capitalized, the assignment can be in the form of instantiation

number

Numeric type - number (integer and floating point)

In addition to supporting decimal and hexadecimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015.

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;

string

  • string single quotation mark (recommended) or double quotation mark or ` ` is OK

    let name: string = "bob";
    name = "smith";

boolean

  • boolean true/false value

    let isDone: boolean = false;

undefined

  • Indicates that there should be a value here, but there is no value now

  • If a variable is declared but not assigned, the variable is undefined

  • In TS, you can re assign undefined to the basic data type variables of existing types

    let u: undefined = undefined

null

  • Indicates that there should be no value here. There is no value

  • In TS, you can re assign null to a reference data type variable of an existing type

    let n: null = null

object

Object type basic usage

  • There are too many objects in js. After adding an object, there are no restrictions on adding types, and development is rarely used

  • Example 1:

    // {} also represents an object, indicating that the variable o must be an object type in which the attribute type can be specified
    // The following example shows that the object o can only have the specified attribute name, type, and number
    // Add?, after the attribute name?, Indicates that the attribute is optional
    let o: {
    	name: string, 
    	age: number,
    	sex?: string
    };
    
    o = {name: 'Sun WuKong',age: 18} // ok
    o = {name: 'Sun WuKong'} // An error is reported. An age attribute is missing
    o = {name: 'Sun WuKong',age: 18,sex: 'male'} // ok
    

    Example 2:

    // Requirement: in an object, only one attribute is required, and the name, type and number of other attributes are unknown
    let o: {
    	name: string, 
    	[propertyName: string]: any
    }
    
    /*
    * In the above code, [propertyName: string] means that the property name is string (the property names of objects are all string types)
    * [propertyName: string]: any Indicates that the attribute in the object is of any type,
    *						If any is a string, it means that the attributes in the object must be of type string
    */
    

    Example 3:

    function getObj(obj: object):object {  
    	// do something  
    	return {    
    		name:"Kakassi"  
    	}
    }
    
    console.log(getObj({name:"Sasuke"}))
    console.log(getObj(new String('character string')))
    

Function writing in object type

Specifies the type of function in the object

  1. Writing method 1: sayHi(name:string):void

    const user: {  
    	name:string  
    	sayHi(name:string):void
    }  
    
    user = {  
    	name:'Zhang San'  
    	sayHi(name) {    
    		console.log('Hello,My name is' + name)  
    	}
    }
    
  2. Writing method 2: add (N1: number, N2: number) = > number

    const user: {  
    	name:string  
    	add(n1:number, n2:number) => number
    }
    
    user = { 
    	name:'Li Si'  
    	add: function(a, b){    
    		return a+b  
    	}
    }
    

array

  • Array; In development, the elements in the array are of the same type

  • Syntax 1: type []

    // Represents an array of values
    let list: number[];
    let list: Array<number>;
    
    let list: number[] = [1, 2, 3];
    
  • Syntax: element type 2, using

    // Represents an array of strings
    let list: string[];
    let list: Array<string>    
    
    let list: Array<number> = ['a', 'b', 'c'];
    

Extension: 2D array

let arr:number[][] = [
	[1,2,3],[7,8,9]
]

function

Definition of function type

  • The function mainly limits the type and number of input and output parameters. There is no fixed targeted syntax and there are many ways to implement it
  1. Individually restricted access parameter type

    • Common ways to write arrow functions

      //Arrow function
      let addFunc = (num1:number, num2:number):number => {
      return num1 + num2
      }

      addFunc = function(n1, n2): number{
      return n1 + n2;
      }
      console.log(addFunc(2, 6)) // 8

      //Function declaration
      function add(num1:number, num2:number):number {
      return num1 + num2
      }
      console.log(add(2,2)) // 4

  2. Use type alias

    type AddFun = (num1:number, num2:number):number
    
    const add:AddFun = (num1, num2) => {  
    	return num1 + num2
    }
    
    • Note: only suitable for function expressions

      // Function expression
      let fun1 = function(){}
      
      // Function declaration
      function fun2(){}
      
  3. Use interface

    • In order to use an interface to represent a function type, you need to define a call signature for the interface

      interface ISearchFunc {
      //Define call signature
      (source:string, subString:string): boolean
      }

      //Define a function, and this type is the above interface
      const searchString: ISearchFunc = function (source:string, subString:string): boolean {
      return source.search(subString) > -1
      }

      //Call
      console.log(searchString('the trace is blocked and long, the line will arrive ',' long ') / / true

Extension - parameters of the function

Default value

function(name: string, age: number = 18){

}

Optional parameters

  • add to?, The interface is also applicable (the representation attribute can be omitted)

  • Add?, after the input parameter variable name, Note that optional parameters must be placed last, and can be one or more optional parameters

  • Non null check related logic is required for optional parameters in the function body

    //Indicates the input parameter age, sex, which can be omitted
    function(name: string, age?: number, sex?: string){

    }

TS new type

any

  • Any type (any can be omitted), try not to use any

  • When set to this type, it turns off the type detection of TS for variables and directly lets them pass the check at the compilation stage

  • Can be assigned to any type of variable

  •   // eg1: no error is reported for multiple assignments
      let a: any = 123
      a = "str"a = true
      
      // eg1: it can be assigned to any other type, so that other types are also called any type
      // The simple understanding is that b is an any type. After the following assignment, a also becomes an any type
      let b: number = 123
      b = a
    

unknown

  • Value of unknown type; In coding, try to use unknown instead of any

  • Similarities and differences between and any

    1. Same: values of different types can be assigned multiple times
    2. Different: any can be assigned to any type of value, which is also called the value of any, but unknown cannot directly assign other types of values
  • Generally speaking, this type is not written by the developer, but transmitted from the network. It needs to be matched and asserted (the type of this variable needs to be specified when using it, and the type can be specified multiple times)

    type A = {name:string}
    type B = {age:number}
    // Simulate the data passed by ajax
    let c: unknown = JSON.parse("{'name':"Tom"}") 
    
    let var1 = (c as A).name
    let  var2 = (c as B).age
    

void

  • Null value, used for function return value, indicating that the function has no return value (common)

  • In actual coding, you can return null or return undefined, but it doesn't make sense. It should be grammatically compatible

    function fn(): void{
    // do something
    return; // Or don't write return
    }

never

  • The type of value that never exists
  • It is rarely used in development. It is generally used for function return types that throw exceptions and infinite loops
  • When this type occurs, pay attention to check whether there is a problem with the code

Syntax:

// The function returning never must have an unreachable end point
function error(message: string): never {    
	throw new Error(message);
}

// The inferred return value type is never
function fail() {    
	return error("Something failed");
}

// The function returning never must have an unreachable end point
function infiniteLoop(): never {    
	while (true) {
	}
}

eg:

type Code = 1|2|3|undefined
let dir:Code // Indicates that the value of dir can only be one of "1, 2, 3, undefined"
switch(dir){    
	case 1:        
		break;    
	case 2:        
		break;    
	case 3:        
		break;    
	case undefined:      
		break;    
	default:        
		console.log('If you enter this branch, it means dir The value of is not in '1, 2, 3, undefined"in, mean never type')}

tuple

  • Fixed length array (element types can be inconsistent)

  • In combination with array understanding, the biggest difference is that the length of tuples is fixed, and the element type corresponding to each index is fixed

  • For values, you can get, set and update. Note that the changed value can only be the specified type. For update, you can use arr [0] = newvalue, and for set, you can use arr.push(newValue)

    // Indicates that there can only be two string elements in the array, and the length is immutable
    let arr1: [string, string]
    
    let arr2: [number, string] 
    

enum

  • Enumeration; The default enumeration value is numbered, similar to array index, starting from 0

eg1:

enum Gender {     
	Male,     
	Female
}

let tom: Gender = Gender.Male
console.log(tom)  // 0
console.log(Gender.Male, Gender.Female) // 0 1
  • Special usage:

If the enumeration value is a numeric value, you can write it in the following way

enum Color {  
	Red = 6,  
	Green = 7,  
	Blue = 8
}

let c:string = Color[6]  // Red

Union type

  • Combine multiple types into one type (indicating that the value can be one of multiple types)

  • Separate with 𞓜

    //The param representing the input parameter can be of type number or string
    //The output parameter is of string type
    function getSomeThing(param: number|string):string {
    return param+''
    }

    getSomeThing(123)
    getSomeThing("string")

    type MyType = 1 | 2 | 3 | 4 | 5;

    let a: MyType = 2;
    let b: MyType = 4;

    //In the array, there can be either strings or numbers
    let arr:(number|string)[]

    arr = [123, 'ha ha'] a
    rr = [66, 88, 99]

typeof operator

Used to get the type of a variable or object

interface Person {  
	name: string;  
	age: number;
}
const test: Person = { name: "Tom", age: 20 };
type Sys = typeof test; // type Sys = Person

In the above code, we obtain the type of the test variable through the typeof operator and assign it to the Sys type variable. Then we can use the Sem type:

const Vivo: Sys  = { name: "Lili", age: 3 }

You can also do the same for nested objects:

const kakaxi = {    
	name: "kakaxi",    
	age: 27,    
	address: {      
		province: 'Hunan',      
		city: 'Changsha'       
	}
}
type Kakaxi = typeof kakaxi;
/*	The following are Kakaxi types 
	type Kakaxi = {    
		name: string;    
		age: number;    
		address: {        
			province: string;        
			city: string;    
		};
	}
*/

In addition, the typeof operator can also be used to obtain the type of function object in addition to the structure type of the object, such as

function toArray(x: number): Array<number> {  
	return [x];
}
type Func = typeof toArray; // -> (x: number) => number[]

Type Asserts

Assertion syntax

  • Same as type conversion in java
  • About assertions is the syntax used to skip compilation checks
  • It is mainly used when TypeScript infers that the type does not meet your needs. You need to specify a type manually.

  • It only works during the compilation phase. TypeScript assumes that you, the programmer, have made the necessary checks.

There are two kinds of syntax, keyword as and tag < >,

  • < type > value
  • Value as type

Since < > will conflict with JSX syntax, it is recommended to uniformly use as for type assertion.

as syntax (recommended):

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

< > syntax:

let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

Assertion extension

Non null assertion!

  • ! Indicates that there must be a value here. Skip the type check

If the compiler cannot remove null or undefined, you can use non null assertions! Manual removal.

function fixed(name: string | null): string {  
	function postfix(epithet: string) {    
		return name!.charAt(0) + '.  the ' + epithet; // name is asserted to be non empty  
	}  
	name = name || "Bob"  
	return postfix("great")
}

Code interpretation:

In line 2, postfix() is a nested function. Because the compiler cannot remove the null s of nested functions (unless it is a function expression called immediately), TypeScript infers that the name in line 3 may be empty.

Line 5, and the code of name = name 𞓜 "Bob" has made it clear that name is not empty, so you can directly assert that name is not empty (line 3).

Double assertion

There are few application scenarios for double assertion. You only need to know that there are such operations:

interface User {  
	nickname: string,  
	admin: boolean,  
	group: number[]
}

const user = 'Evan' as any as User

Code explanation: in the last line, the as keyword is used for two assertions, and the final variable user is forcibly converted to user type.

Extension - other uses of types

Type alias

  • Alias any type. Syntax: type alias = type

  • Usage scenario: when the same type (complex) is used multiple times, the coding of this type can be simplified through type alias

  • You need to use the keyword type and alias name. It is recommended to capitalize the first letter

    type CustomArray = (number|string)[]

    Let arrar1: customarray = [1, 'ah', 6]
    let arr2:CustomArray = ['x', 'y', 8]

A variable specifies multiple types

// Indicates that a can be of type string or number
let a: string | number;

Use & extend

let j:{name: string} & {age: number}

j = {	
	name: 'Kakassi',  
	age: 25
}

j = {name: 'Naruto'} // An error is reported and an age attribute is deleted

Overview of inheritance and Implementation

extends

  • Call the parent class to use super
  • Subclasses inherit the properties and methods of the parent class
  • Subclasses can override the properties and methods of the parent class

Class inheritance

Only single inheritance is allowed, but multi-level inheritance is allowed

class A {    
	name:string;    
	constructor(name:string){        
		this.name = name    
	}
}
class B extends A {    
	age:number;    
	constructor(age:number, name:string){        
		// You must first call the parent constructor with super        
		super(name)        
		this.age = age    
	}
}
class C extends B {     
	sex:string;    
	constructor(sex:string, age:number, name:string){        
		super(age,name)        
		this.sex = sex    
	}
}
const instance = new C('Zhang San', 18, 'male')
console.log(instance)
// C {Name: 'male', age: 18, sex: 'Zhang San'}

Interface inheritance

Interfaces can inherit more than one

interface A {    
	id: number
}
interface B {    
	code: string
}
interface C extends A,B {    
	isFlag: boolean
}

const test:C = {    
	id:200,    
	code:'Ling Lingqi',    
	isFlag:false
}

console.log(test)
// {id: 200, code: 'Lingling lacquer', isFlag: false}

implements

  • Implementation is to code the methods specified in interfaces and abstract classes
  • Multiple implementations are possible

Class, interface, abstract class

In TS, the concepts of these three are the same as those in Java, which are only described in the most straightforward and concise language

class

  • The simplest understanding of a class can be seen as the encapsulation of code. For example, an array stores data, while a class can store more and store code

Interface

  • It is simply understood as a kind of constraint and rule
  • Mainly through the definition of abstract methods, let the inherited subclasses to implement
  • Try to understand that if you introduce a plug-in, you need to create a class and write fixed methods for configuration. In the plug-in, you can define the interface to enable the user to implement the interface, and then restrict the user to code the fixed configuration

##Abstract class

  • Development is not commonly used

  • There can be either concrete methods or abstract methods

  • It is the encapsulation of subclasses and public code; It is also a constraint on subclasses and methods that need specific coding

  • It can be understood by combining the functions of the above two

Interface and attribute extension in interface

Interface

  • Compared with java, it can be regarded as a mandatory specification and a constraint

    interface IPerson {
    firstName:string
    lastName:string
    }

    function showFullName (person:IPerson) {
    return ${person.firstName}_${person.lastName}
    }

    let kakaxi:IPerson {
    firstName: 'flag wood'
    lastName: 'Kakashi'
    }

    console.log(showFullName(kakaxi))
    //Flag wood_ Kakassi

Interface inheritance

  • And class inheritance is a concept

  • TS supports inheriting multiple interfaces

    interface point2D {  
    	x: number   
    	y: Number }
    interface point3D {    
    	z: number 
    }
    interface point4D extends point2D, point3D {   
    	w: number
    }
    
    const pointTest: point4D = {    
    	x: 100, 
    	y: 200, 
    	z: 300, 
    	w: 400
    }
    console.log(pointTest)
    

Extension - read only and can be omitted

  • readonly read only

  • Can be omitted

    interface IAnimals {
    //id is a read-only number type
    readonly id:number
    name:string
    age:number
    //sex can be omitted
    sex?:string
    }

    const dog:IAnimals = {
    id: 1,
    name: 'Laifu',
    age: 2,
    sex: 'male'
    }

Class, inheritance, super

Concept of class

  • Analogy Java
  • The type of the class is defined through the interface
  • A class can implement multiple interfaces at the same time
  • The constructor constructor defined in the class is to initialize the attribute value when instantiating
  • Interfaces and between interfaces: Inheritance
  • Between classes and interfaces: Implementation
interface IFly {    
	fly:()
}

// Define a class whose type is the interface defined above
class Person implements IFly {    
	fly() {        
		console.log("Fly to the sky, side by side with the sun")    
	}
}

const p1 = new Person()
p1.fly()


interface IFly {    
	fly:()
}
interface ISwim {    
	swim:()
}

class Person implements IFly,ISwim {    
	fly() {        
		console.log("Can fly")    
	},     
	swim() {        
		console.log("Can swim")    
	}
}

const p2 = new Person()
p2.fly()
p2.swim()


interface TMyFlyAndSwim extends IFly,ISwim {}
class Person implements TMyFlyAndSwim {    
	fly() {        
		console.log("Can fly")    
	},     
	swim() {        
		console.log("Can swim")    
	}
}

const p3 = new Person()
p2.fly()
p2.swim()

inherit

  • Year on year Java

  • super keyword can call the constructor of the parent class or the instance function in the parent class

    class Person {    
    	name:string    
    	age:number    
    	gender:string    
    	sayHi(food:string){        
    		console.log(`I am ${this.name},like ${food}`)   
    	 }    
    	 constructor(name:string,age:number,gender:string) {       
    	 	this.name = name        
    	 	this.age = age        
    	 	this.gender = gender    
    	 }
    }
    
    class Student extends Person {   
    	constructor(
    		name:string,
    		age:number,
    		gender:string) {        
    			// Using super, call the constructor instantiation of the parent class        
    			super(name,age,gender) { 
    		}    
    		// Call the method in the parent class    
    		sayHi(food:string) {       
    			super.sayHi(food)    
    		}
    }
    
    const p1 = new Person("Zhang San",25,"male")
    p1.sayHi('watermelon') // I'm Zhang San. I like watermelon
    
    const s1 = new Student('Xiao Ming',18,'male)
    s1.sayHi('strawberry') // I'm Xiao Ming. I like strawberries
    

polymorphic

  • Parent class reference, pointing to child class objects

  • Different types of objects produce different behaviors for the same method

    class Animal {
    name:string
    constructor(name:string){
    this.name = name
    }
    run(distance:number) {
    console.log(${this,name} ran ${distance} meters)
    }
    }

    class Dog extends Animal {
    constructor(name:string) {
    super(name)
    }
    //Override run function
    run(distance:number) {
    console.log(${this,name} ran ${distance} meters ----- dog)
    }
    }

    class Pig extends Animal {
    constructor(name:string) {
    super(name)
    }
    //Override run function
    run(distance:number) {
    console.log(${this,name} ran ${distance} meters = = = = = = pig)
    }
    }

    const ani:Animal = new Animal('animal ')
    ani.run()

    const dog:Animal = new Dog('wangcai ')
    dog.run()

    const pig:Animal = new Pig('page ')
    pig.run()

    //Use polymorphism
    Const dog1: Animal = new dog
    dog1.run()
    const pig1:Animal = new Dog('pig ')
    pig1.run()

Modifier

Used to describe the accessibility of members (properties, constructors, functions) in a class

  • Public: default; Represents a public, decorated member that can be accessed from any location;
  • Private: refers to private and modified members, which can only be accessed in the class; The subclass cannot be accessed in the class (this.xxx);
  • Protected: refers to the protected and modified member, which can be accessed in the subclass (this.xxx); External inaccessible;

generic paradigm

Basic concepts

Generics is to solve the reusability of classes, interfaces and methods, as well as support for unspecified data types

  • The function name is followed by < >. Generally, the symbol t is used to occupy the position, and T represents the specific type

  • The types of input and output parameters are generally related

    function identity(...arg: T[]): T[] {
    return [...arg]
    }
    console.log(identity(1,2,3))

keyof keyword

keyof is used to get all keys of a certain type, and its return type is union type

Code interpretation:

Indicates that it can only be an incoming OOo type. One of the attributes in the OOO type ("id" | "code" | "age")

let obj = {    
	id:"100",    
	code:996,    
	age:18
}
type OOO = typeof objfunction main<T, P1 extends keyof T>(obj:T, prop1: P1) {  
	console.log(obj[prop1]);
}

main(obj, 'id');   // '100'
main(obj, 'code'); // 996
main(obj, 'age');  // 18

Generic constraints

Generics can represent any type, but in actual coding, sometimes you can know the approximate range of types,

In order to avoid using errors, the use range of types is limited to generics, which is called generic constraint (narrowing the value range of types)

  • It is generally realized in two ways
    1. Specify more specific types
    2. Add constraint

eg1: the restricted access parameter is an array, and the element type of the array is not fixed

function func<T>(param: T[]): T[] {  
	return param
}

func([1,2,3,4])

eg2: the type passed in must contain the length attribute

interface ILength {    
	length: number
}
function getId<T extends ILength>(param: T): T {    	
	console.log(param.length)    
	return param
}

// Although strings and arrays do not inherit ILength, they have their own length attribute
console.log(getId('NongFu Spring'));
console.log(getId([11,33,44]));

eg2: the type passed in is an object, which must have name and age attributes

interface IUser {  
	name: string  
	age: number
}

function func<T extends IUser>(param: T): T {  	
	console.log(param.name)    
	console.log(param.age)    
	return param
}

Use of generics in interfaces

interface IUser<T> {  
	getId: (param: T) => T
}

Generic utility class

  • Generic tool types: TS has built-in some common tool types to simplify some common operations in TS
  • Note: they are all implemented based on generics (generics are applicable to many types and more general), and they are built-in and can be used directly in the code. There are many types of these tools, mainly learning the following:
  1. Partial<Type>
  2. Readonly<Type>
  3. Pick<Type, Keys>

Partial

  • Partial is used to construct (create) a Type and set all properties of the Type to optional.

    type Props = {
    id: string
    children: number[]
    }

    type PartialProps = Partial

  • Explanation: the new type PartialProps constructed has the same structure as Props, but all properties become optional.

Readonly

  • Readonly is used to construct a Type and set all properties of the Type to readonly.

    type Props = {
    id: string
    children: number[]
    }

    type ReadonlyProps = Readonly

  • Explanation: the structure of the constructed new type ReadonlyProps is the same as that of Props, but all properties become read-only.

    let props: ReadonlyProps = {
    id: '1',
    children: []
    }
    //Error demonstration
    props.id = '2'

  • When we want to re assign the id attribute, we will report an error: we cannot assign it to "id" because it is a read-only attribute.

Pick

  • Pick < Type, keys > select a set of attributes from Type to construct a new Type.

    interface Props {
    id: string
    title: string
    children: number[]
    }
    type PickProps = Pick<Props, 'id' | 'title'>

  • Explanation:

    1. The Pick tool type has two type variables: 1 indicates whose attributes are selected, and 2 indicates which attributes are selected. 2. For the second type variable, if only one is selected, only the attribute name can be passed in.
    2. The attribute passed in by the second type variable can only be the attribute existing in the first type variable.
    3. The constructed new type PickProps has only two attribute types: id and title.

Keywords: Javascript Front-end TypeScript html Interview

Added by JoeCrane on Mon, 21 Feb 2022 13:22:14 +0200