TypeScript learning notes
- TypeScript overview and environment
- JS original type
- TS new type
- Type Asserts
- Extension - other uses of types
- Overview of inheritance and Implementation
- Class, interface, abstract class
- Interface and attribute extension in interface
- Class, inheritance, super
- polymorphic
- Modifier
- generic paradigm
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:
-
Open the VSCode terminal.
-
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.
- 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
-
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) } }
-
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
-
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
-
-
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(){}
-
-
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
- Same: values of different types can be assigned multiple times
- 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
- Specify more specific types
- 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:
- Partial<Type>
- Readonly<Type>
- 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:
- 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.
- The attribute passed in by the second type variable can only be the attribute existing in the first type variable.
- The constructed new type PickProps has only two attribute types: id and title.