This article aims to familiarize yourself with typescript syntax

1. Run typescript code using TS-Node

  1. Ts – node installation
npm install ts-node -g
Copy the code
  1. Ts-node also relies on tslib and @types/node packages:
npm install tslib @types/node -g
Copy the code
  1. You can now run TypeScript code directly from TS-Node
ts-node demo.ts
Copy the code

Typescript data types

2.1 Definition of variables

Var /let/const identifier: data type = assignment

2.2 Javascript native types

2.2.1 number type

// Declare a variable of type number
let num1: number = 100;
let num2: number = 0b100; / / binary
let num3: number = 0o100; / / octal
let num4: number = 0x100; // Hexadecimal
Copy the code

2.2.2 Boolean type

// Declare a variable of type Boolean
let bool:boolean = true 
Copy the code

2.2.3 type string

// Declare a variable of type string string
let message: string = "hello typescript"; 
Copy the code

2.2.4 Null and undefined

let n: null = null
let u: undefined = undefined
Copy the code

2.2.5 Array type

// Declare the Array type Array
let arr: Array<number> = [1.2.3]; / / way
let arr1: number[] = [1.3.4]; 2 / / way
Copy the code

2.2.6 Object type

// Declare an object type object
let obj: object = { name: "coder" }; // The property cannot be set or retrieved from obj

// obj1 object contains
// A string name attribute
// An age attribute of type number
// An optional string phone attribute? : indicates optional
const obj1: {name: string.age:number, phone? :string} = {
  name: 'coder'.age: 22
}
Copy the code

2.2.7 Symbol type

let name: symbol = Symbol("coder");
Copy the code

2.2.8 Function Types

  1. Assign a type to the parameter

  2. Assign a type to a return value (you can usually leave the return value type out of development because it is automatically derived)

    function foo(num1: number, num2: number) :void {
    	console.log(num1, num2)
    }
    Copy the code
  • Functions in context may not add type annotations

    const names = ['zhangsan'.'lisi'.'wangwu']
    // forEach can omit the type of the function argument, since the context can infer that it is a string
    names.forEach(item= > {
      conosle.log(item)
    })
    Copy the code
  • A detailed written

Num1 and num2 are mandatory
const add: (num1: number, num2: number) = > number = (a1: number, a2: number) = > {
  return a1 + a2;
};
Copy the code

2.3 New typescript types

2.3.1 any type

let messgae:any = 'hello typescript'
messgae = 1
messgae = true
Copy the code
  • A variable can be of type any when its type cannot be determined and it may change somewhat
  • The any type is a bit of a neat TypeScript device
    • You can perform any operation on a variable of type any, including retrieving nonexistent attributes and methods.
    • A variable of type any can be assigned any value, such as a number or string.

2.3.2 unknown type

Unknown is a special type in TypeScript that describes variables of uncertain type.

let messgae:unknown = 'hello'
Copy the code
  • The difference between unknown and any types

    • Any type: can be understood as any type and can be assigned to any type
  • Unknown type: can be understood as an indeterminate type, which can only be assigned to any and unknown types

2.3.3 void type

Void is usually used to specify that a function has no return value, so its return value is void:

Null and undefined can be assigned to void, i.e. functions can return either null or undefined

function foo() {
	console.log(123)}Copy the code

This function does not write any type, so its default return value is of type void, or it can be explicitly returned

function foo() :void {
	console.log(123)}Copy the code

2.3.4 Association Type

/ / foo said can be either a string can also be a number let foo: string | number = '123' foo = 123Copy the code

2.3.5 Crossing Types

// foo is both a string and a number. Foo is a never
let foo: string | number
Copy the code

2.3.6 never type

Never indicates the type of value that never occurs, such as a function

// 1. The function throws an exception that never returns
function foo() :never {
	throw new Error()}// 2. The function never returns a value in an infinite loop
function foo1() :never {
  while(true) {
    cosnole.log(123)}}// 3. The variable check is of type never and never has a value. In functions, check is assigned when message is of type Boolean
function foo2(messgae: string | number | boolean) {
  switch (typeof messgae) {
    case "string":
      console.log(123);
      break;
    case "number":
        console.log(123);
        break;
    default:
      const check: never = messgae; // * Cannot assign type "Boolean" to type "never"}}Copy the code

2.3.7 Tuple type

  • A combination of elements
// We can make sure that the first variable of the info array is string typed and the second variable is number
const info: [string.number] = ["string".123]
Copy the code

Application scenarios

  • The React of useState
[T, (newState: T) => void] [T, (newState: T) => void]
function useState<T> (state: T) :T, (newState: T) = >void] {
  let currentState = state
  
  const changeState = (newState: T) = > {
    currentState = newState
  }

  return [currentState, changeState]
}
Copy the code

3. Typescript type supplement

3.1 Type Alias

  • Type is used to define type aliases
type IDType = string | number | boolean
let id: IDType = '123'
id = 123
id = true
Copy the code

3.2 Type Assertion AS

  • Sometimes Type Assertions may be required when TypeScript cannot get specific Type information.

    • For example, with Document.getelementById, TypeScript only knows that the function returns HTMLElement, but not its type
    const el = document.getElementById("img") as HTMLImageElement; // Get HTMLElement by default, convert to the specific HTMLImageElement type
    el.src = "Url";
    Copy the code
  • TypeScript only allows type assertions to be cast to more or less specific versions of types. This rule prevents impossible casts

    Const num:number = 1123 num as string // × The conversion from type "number" to type "string" may be an error because the two types do not overlap sufficiently. If this is intentional, first convert the expression to "unknown".Copy the code

3.3 Non-null type assertion!

  • The following code generates an error during compilation of ts:

    • This is because the incoming message may be undefined, and the method cannot be executed.
function foo(message? :string) {
	console.log(message.length);
}

foo("123");
Copy the code
  • Non-null type assertions can be used at this point
    • Non-empty assertions use! , indicating that an identifier can be determined to have a value, skipping ts’s detection of it during compilation;
function foo(message? :string) {
  console.log(message? .length); } foo("123");
Copy the code

3.4 optional link chain

  • Optional chains aren’t actually a TypeScript unique feature; they’re an addition to ES11 (ES2020)
    • Optional chain using optional chain operator? ,
    • Its function is when the object attribute does not exist, will short circuit, directly return undefined, if there is, then will continue to execute;
    • Although optional chain operations are a feature of ECMAScript, they work with TypeScript in later versions;
typePerson = { friend? : { name? :string;
    age: number;
  };
};
const obj: Person = {};

// console.log(obj.friend.name); // * obj. Friend = obj
console.log(obj.friend?.name) // undefined
Copy the code

3.5?? And!!!!!

  • n !! Operator: converts an other type to Boolean;
  • ?? Operator: new feature added in ES11, null value merge operator (??) Is a logical operator that returns its right-hand operand if the left-hand side of the operator is null or undefined.

?? And | | difference: | | is when the left can be turned into a null or undefined returns the right operand

const foo = 0 || 1
const foo1 = 0 ?? 1
console.log(foo) / / 1
console.log(foo1) / / 0
Copy the code

3.6 Literal types

const message: 'hello' = 'hello'
Copy the code

This doesn’t make much sense by default, but we can combine multiple types together;

type Alignment = 'right' | 'left' | 'center'
const align: Alignment = 'right'
Copy the code

3.7 Literal reasoning

const info = {
  name: 'coder'.sex: 'male'
}

function readInfo(name: string, sex: 'male' | 'female') {
  console.log(name, sex)
}

readInfo(info.name, info.sex) / / x error Because objects to literal reasoning, the info is actually a {name: string, sex: string}, the parameters of type "string" cannot be assigned to type "" male" | "female" "parameter.
Copy the code

The solution

/ / way
readInfo(info.name, info.sex as 'male')
Copy the code
2 / / way
const info = {
  name: 'coder'.sex: 'male'
} as const
/* Const info: {readonly name: "coder"; readonly sex: "male"; } * /
Copy the code
3 / / way
type Person = {
  name: string.sex: 'male' | 'female'
}
const info: Person = {
  name: 'coder'.sex: 'male'
}

function readInfo(name: string, sex: 'male' | 'female') {
  console.log(name, sex)
}

readInfo(info.name, info.sex)
Copy the code

3.8 Type Reduction

Type Narrowing Type Narrowing: In a given execution path, we can narrow a Type smaller than the declared one. This process is called Narrowing

Common type narrowing

  1. typeof

    type IDType = string | number
    
    let id:IDType 
    
    console.log(id.length) // × Type "IDType" does not have the attribute "length". Attribute 'length' not present on type 'number'
    if(typeof id === 'string') {
      console.log(id.length) // Since we already know that id is a string, we can call the properties and methods of string directly
    }
    Copy the code

    Similarly, equality narrowing (===! ==), instanceof, in, etc.,,

3.9 Type derivation of this

  • Explicit type default derivation
  • The following code works, which means that TypeScript believes that our this will be used correctly at compile time:
    • TypeScript assumes that eating has an external object, info, corresponding to this, so it treats this as that object when used.
const info = {
  name: "coder".eating() {
    console.log(this.name); }}; info.eating();// coder
Copy the code
  • An ambiguous type
function eating() {
  console.log(this.name)
}

const info = {
  name: "coder",
  eating
};

info.eating(); // * An error is reported
Copy the code
- Solution: Specify the typeCopy the code
function eating(this: { name: string }) {
  console.log(this.name)
}

const info = {
  name: "coder",
  eating
};

info.eating(); 
eating.apply(info)
Copy the code

3.10 Function overloading

function add (num1:number| string, num2:number|string) {
  return num1 + num2 / / * operator "+" cannot be applied to type "string | number" and "string | number"
}
Copy the code
  • If you want to be able to add string and number types, you can use function overloading
function add (num1:string, num2: string) : number
function add (num1:number, num2: number) : number
function add (num1:number, num2: string) : number
function add (num1:string, num2: number) : number

function add (num1:any, num2:any) :any {
  return num1 + num2
}

add(10.20// Line 2 of the function definition is executedadd(10.'20'// Line 3 of the function definition is executedCopy the code

4. Classes in Typescript

4.1 Class definition

  • Use the class keyword to define a class;
  • Declare some class attributes: Declare the attributes of the class and their corresponding types inside the class
    • If the types are not declared, they default to any;
    • You can also set initialization values for properties;
    • In the default mode of strictPropertyInitialization attribute below is must be initialized, if there is no initialization, then compile time complains; If you want to uninitialize, you can use name! : string syntax
  • Classes can have their own constructor, which is called when we create an instance with the new keyword;
    • The constructor does not return any value. By default, it returns the currently created instance.
  • Classes can have their own functions, defined functions called methods;
class Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  eating() {
    console.log(this.name + " is eating"); }}const p = new Person("coder".22);
p.eating();

Copy the code

4.2 Class inheritance

  • One of the features of object orientation is inheritance, which can not only reduce the amount of code, but also the premise of the use of polymorphism
  • The extends keyword is used for inheritance and super is used in subclasses to access the parent class
class Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  eating() {
    console.log(this.name + " is eating"); }}class Student extends Person {
  sno: string;
  constructor(name: string, age: number, sno: string) {
    super(name, age);
    this.sno = sno;
  }

  studying() {
    console.log("Student id is" + this.sno + "The students are learning"); }}const s = new Student("yjw".22."001");
s.eating();
s.studying();

Copy the code
  • The Student class can have its own properties and methods and will inherit from Person;

  • In the constructor, the constructor of the parent class is called by super to initialize the attributes in the parent class.

4.3 Class member modifier

  • In TypeScript, class properties and methods support three modifiers: public, private, and protected
    • Public modifies properties or methods that are public and visible anywhere. Properties written by default are public.
    • Private modifies properties or methods that are visible only in the same class and are private;
    • Protected modifies properties or methods that are visible only within the class itself and its subclasses.
  • Public is the default modifier and can be accessed directly. Here’s a demonstration of protected and private.
class Person {
  private name: string;
  protected age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  eating() {
    console.log(this.name, this.age); }}class Student extends Person {
  sno: string;
  constructor(name: string, age: number, sno: string) {
    super(name, age);
    this.sno = sno; }}const p = new Person("coder".22);
// console.log(p.name); The compile error attribute "name" is private and can only be accessed in the class "Person".
// console.log(p.age); // × The compile error attribute "age" is protected and can only be accessed in class "Person" and its subclasses.
p.eating(); / /)
Copy the code

4.4 Read-only property readonly

  • If you have an attribute that you do not want to be modified by the outside world, but you want to use it directly, you can use readonly:
class Person {
  readonly name:string
  constructor(name: string) {
    this.name = name
  }
}

const p = new Person('coder')

p.name = 'coderyjw' // × cannot be assigned to "name" because it is read-only
Copy the code

4.5 getters/setters

Some of the private properties that we can’t access directly, or some of the properties that we want to listen to get getters and set setters,

At this point we can use accessors.

class Person {
  private _name: string;

  constructor(name: string) {
    this._name = name;
  }

  get name() :string {
    return this._name;
  }
  set name(newName) {
    this._name = newName; }}const p = new Person("coder");

p.name = 'coderyjw'
console.log(p.name);

Copy the code

4.6 static Static member

Used to define members and methods at the class level.

class Person {
  static time: string = "2021-12-26";
}

console.log(Person.time);

Copy the code

4.7 the abstract class

Classes defined by abstract are called abstract classes
// Abstract classes cannot be instantiated, abstract classes
// An abstract class must have abstract methods
abstract class Shape {
  // Abstract defines functions as abstract functions
  // Abstract methods must exist in abstract classes;
  // An abstract method must be implemented by a subclass, otherwise the class must be an abstract class;
  abstract getArea(): number; 
}

class Circle extends Shape {
  r: number;
  constructor(r: number) {
    super(a);this.r = r;
  }
  getArea(): number {
    return this.r * this.r * Math.PI; }}const c = new Circle(5);
console.log(c.getArea());
Copy the code

5. Typescript interfaces

5.1 Interface Declaration

interface Person {
	name: string.age: number
}
Copy the code

5.2 Optional Properties

interface Person {
	name: string, age? :number
}
Copy the code

5.3 Read-only Properties

interface Person {
	readonly name: string.age: number
}
Copy the code

5.4 Index Type

interface INdexLanguage  {
  [index: number] :string
}

const Language: INdexLanguage = {
  '0': 'javascript'.'1': 'java'.'2': 'c',}Copy the code

5.5 Function Types

interface CalcFn {
  (n1:number.n2: number) :number
}

const add: CalcFn = (n1:number, n2:number) = > {
  return n1 + n2
}
Copy the code

5.6 Interface Inheritance

interface Person {
  name: string
}

interface Animal {
  running: () = > void
}

/ / multiple inheritance
interface Student extends Person, Animal {
  sno: number
}
Copy the code

5.7 Interface Implementation

  • An interface can be implemented by a class through the implements keyword
    • A class can implement multiple interfaces, and must implement the corresponding properties and methods in the interface;
    • If implemented by a class, that class can be passed in wherever the interface needs to be passed later.
interface Person {
  name: string;
}

class Student implements Person {
  name: string;
  sno: string;

  constructor(name: string, sno: string) {
    this.name = name;
    this.sno = sno; }}function study(p: Person) {
  console.log(p);
}

const s = new Student("coder"."001");
study(s);
Copy the code

5.8 Differences between Interface and Type

  • If you are defining non-object types, you are usually advised to use type, such as Direction, Alignment, and some functions.
  • If you define an object type, then they are different:
    • Interface can repeatedly define properties and methods for an interface;
    • Type defines an alias, which cannot be repeated.
  1. Interface You can define the same interface repeatedly
interface IPerson {
  name: string;
}

interface IPerson {
  name: string;
  age: number;
}

class Person implements IPerson {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age; }}Copy the code
  1. Type cannot define the same alias repeatedly
Type Person = {name: string} // × Identifier "Person" is repeated. type Person = { name: string age: number }Copy the code

6. Enumeration types

  • Enumerated types are one of the few TypeScript features that does:
    • Enumeration is a set of possible values, one by one, defined in a type, this type is enumeration type;
    • Enumerations allow developers to define a set of named constants, which can be numbers or strings;
enum  Direction {
  LEFT,
  RIGHT,
  TOP,
  BOTTOM
}
Copy the code

Enumeration types have values by default

The enumerated values above can be seen as

enum  Direction {
  LEFT = 0,
  RIGHT = 1,
  TOP = 2,
  BOTTOM = 3
}
Copy the code

Other values can also be assigned manually

7. The generic

7.1 Understanding generics

  • Generics: Parameterize types
    • You need to use a characteristic variable here, type variable, that applies to types, not values
function foo<T> (arg: T) :T { 
  return arg
}
Copy the code

The above function can be called in two ways:

  • Method one: pass the type to the function by < type >
  • By type push, automatically push out the type of the variable we passed in
/ / way
console.log(foo<string> ('hello'))
console.log(foo<number> (1))

2 / / way
console.log(foo('hello'))
console.log(foo(1))
Copy the code

7.2 Basic Supplements

Multiple types can be passed:

function foo<T,K>(a1: T, a2: K) {

}
Copy the code
  • We might see some common names in development:
    • T: short for Type
    • K, V: short for key and value, key-value pair
    • E: Short for Element
    • O: Object

7.3 A generic interface

interface IPerson<T> {
	name: T,
  friends: T[]
	foo: (num: T) = > void
}
Copy the code

7.4 A generic class

class Person<T> {
	x: T
  y: T

  constructor(x: T, y: T) {
    console.log(x, y)
  }
}
Copy the code

7.5 Generic constraints

  • Sometimes we want the types passed in to have some commonality, but these commonalities may not be in the same type:
    • For example, string and array have length, or some objects have length;
    • So as long as the length of the property can be used as our parameter type, so how to operate?
interface ILength {
  length: number;
}

function getLength<T extends ILength> (l: T) {
  console.log(l.length);
}

getLength("123");
getLength([1.2.3]);

Copy the code