Why it works: JavaScript is a dynamically weakly typed language;

I. Introduction case

npm init -y= >package.json
npm install -g typescript

tsc -v
tsc --init= >tsconfig.json
// Create a new test.ts file
var message:string = "Hello World" 
// Execute the following command to convert TypeScript to JavaScript code:
tsc test.ts
// A test.js file will be generated in the current directory (the same directory as test.ts) with the following code:
var message = "Hello World";
Copy the code

Two, basic types

Type annotations

  • Function: equivalent to type declarations in strongly typed languages;

  • Syntax: (variable/function) : type

// Primitive type;
let bool: boolean = true
let num: number = 123
/ / array;
let arr1: number[] = [1.2.3]
let arr2: Array<number> = [1.2.3]  // Use array generics
// undefined,null
let un: undefined=undefined
let nu: null=null
/ / function.
let add =(x: number,y: number) = >x+y
/ / object;
let obj: {x: number.y: number} = {x:1.y:2}
obj.x=3

/ / a tuple; The tuple type is used to represent an array with a known number and type of elements. The types of each element need not be the same.
let tuple: [number.string] = [0.'1']
// symbol; Only the value of the
let s1: symbol = Symbol(a)let s2=Symbol(a)//console.log(s1===s2) false
// void -- Identifies the type of value returned by the method, indicating that the method does not return a value.
function warnUser() :void {
    console.log("This is my warning message");
}
// any -- variables declared as any can be assigned values of any type.
let x;
// never -- never is a subtype of other types, including null and undefined, and represents a value that never occurs.
let error=() = >{
    throw new Error('error')}let endless=() = >{
    while(true){}
}
Copy the code

assertions

1. Type assertion

Type assertions are used to manually specify the type of a value. (that is, knowing that the object is of a type, using a post-compiler can bypass type checking)

Syntax format:

// < type > value or
// Value as type

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
        
let strLength: number = (someValue as string).length;


// Type assertion that the bar variable is of type foo.
var foo = <foo>bar;		
var foo = bar as foo;
Copy the code

🔴 as operator

TypeScript disables type assertions using Angle brackets in.tsx files.

2. Non-null assertions

A new postfix expression operator in context when the type checker cannot determine the type! Can be used to assert that operation objects are non-null and non-undefined. Specifically, x! Null and undefined are excluded from the x range.

Three, interfaces,

Interfaces are used to constrain the structure and types of objects, functions, and classes.

// Interface attribute format:
// The interface defines the object:
interface list { 
   readonly id : number; // readonly Indicates that the property is read-only.name ? :string;  / /? Indicates that the attribute is optional
} 

let add : (x:number,y:number) = >number
// Function defined by interface:
// Equivalent to one:
interface Add{
    (x:number.y:number) :number
}
// equivalent to two :(use type aliases for brevity)
type Add = (x:number,y:number) = > number
let add : Add = (a,b) = > a+b
Copy the code

Combine types and interfaces

interface RunOptions { 
    commandline:string[] |string| (() = >string); 
} 
 
var options:RunOptions = {
    commandline:"Hello"  // commandline is a string
}; 
console.log(options.commandline)  // Hello

options = {
    commandline: ["Hello"."World"]  Commandline is an array of strings
}; 
console.log(options.commandline[0]);  // Hello
console.log(options.commandline[1]);  // World

options = {
    commandline:() = >{return "Hello World"; }Commandline is a function expression
}; 
 
var fn:any = options.commandline; 
console.log(fn()); // Hello World
Copy the code

Interfaces and Arrays

TypeScript supports two index signatures: strings and numbers.

You can set the index value and element of an array to different types, and the index value can be either a number or a string.

interface namelist { 
   [index:number] :string // Use numeric index;
} 
var list2:namelist = ["John".1."Bran"]  // Error element 1 is not a string

interface ages { 
   [index:string] :number  // Use string index;
} 
var agelist:ages; 
agelist["John"] = 15   / / right
agelist[2] = "nine"   / / error
Copy the code

Interface inheritance

Interface inheritance means that an interface can extend itself through other interfaces using the extends keyword.

Type the alias

A type alias gives a type a new name.

type Name = string;
type NameResolver = () = > string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver) :Name {
    if (typeof n === 'string') {
        return n;
    }
    else {
        returnn(); }}Copy the code

Interface VS type alias

  1. type(Type alias) cannot be edited twice, whileinterfaceCan be extended at any time (extendsandimplements)
  2. If you cannot describe a type through an interface and need to use associative or tuple types, you usually use type aliases.
// pages/form/basic-form/model.ts
import { AnyAction } from 'redux';
import { EffectsCommandMap } from 'dva';

export type Effect = (action: AnyAction, effects: EffectsCommandMap & { select: 
       
        (func: (state: {}) => T) => T },
       ) = > void;
export interface ModelType {
  namespace: string;
  state: {};
  effects: {
    submitForm: Effect;
  };
}

const Model: ModelType = {
  namespace: 'basicForm'.state: {},
  effects: {*submitForm({ payload }, { call }) {	//... }}};export default Model;
Copy the code

Four, class,

Classes describe the common properties and methods of the objects created.

Class inheritance

  • When you create a class, you inherit from an existing class. The existing class is called a parent class, and the classes that inherit from it are called subclasses.

  • Subclasses cannot inherit the private members (methods and attributes) and constructors of their parent class.

  • You can only inherit one class at A time, not multiple classes, but TypeScript supports multiple inheritance (A inherits FROM B, and B inherits from C).

The static keyword

The static keyword is used to define the class’s data members (properties and methods) as static, and static members can be called directly from the class name.

Access control modifier

  • Public (default) : public and can be accessed anywhere.
  • Protected: It is protected and can be accessed by itself as well as by its subclasses and superclasses.
  • Private: private, accessible only by the class in which it is defined.

The relationship between classes and interfaces:

Classes can implement interfaces using the keyword implements and use the interest field as an attribute of the class.

interface ILoan { 
   interest:number 
} 
 
class AgriLoan implements ILoan { 
   interest:number 
   rebate:number 
   
   constructor(interest:number,rebate:number) { 
      this.interest = interest 
      this.rebate = rebate 
   } 
} 
 
var obj = new AgriLoan(10.1) 
console.log("Profit is:"+obj.interest+", draw into:"+obj.rebate )
// The profit is: 10, and the draw becomes: 1
Copy the code

Five, the function

// Form 1:
function add(x: number, y: number) :number {
    return x + y;
}
// Form 2:
let myAdd = function(x: number, y: number) :number { return x + y; };
// Add a type to each argument and return value of the function
// Note: The return value type is a necessary part of the function type. If the function does not return any value, the return value type must be void instead of empty.
Copy the code

Six, generics

Data types are not predetermined; the specific type is determined at the time of use.

function component(value:any) :any{
   return value
}
// Using any causes this function to accept arg arguments of any type. Note that the type passed in should be the same as the type returned.
// change to a generic function :(type T does not need to be known in advance, and also ensures that the input and output are of the same type)
function component<T> (value:T) :T{
    return value
}
component<string[] > ['a'.'b']);  // Call method one;
component(['a'.'b'])	// Type inference is used

// Use generics to define a function type;
type Component = <T>(value:T) = > T
let myCom:Component=com1

// Generic interface; Generic variables 
      
       (Think of generic variables as function parameters; generic variables are parameters that represent types, not values)
      
interface Com<T> {
    (value:T) : T
}

// Generic class;
class Demo<T> {
    // Put the generic variable after the name of the class so that it can constrain all the members of the class. Note: Generics cannot be applied to static members of a class
    eat(value:T){
        returnvalue; }}Copy the code

Generic constraint

function loggingIdentity<T> (arg: T) :T {
    console.log(arg.length);  // Error: T doesn't have .length
    return arg;
}

// 1. Define an interface to describe the constraint, that is, create an interface with the.length attribute;
// 2. Use this interface and the extends keyword to implement constraints
interface Lengthwise {
    length: number;
}
function loggingIdentity<T extends Lengthwise> (arg: T) :T {
    console.log(arg.length);  // Now no error
    return arg;
}
Copy the code

7. Advanced types

Cross type

Cross typing is merging multiple types into one type. This allows us to superimpose existing types into a single type that contains all the required features of the type. (&)

The joint type

Union types indicate that a value can be one of several types. Using a vertical bar (|) separated for each type.

interface Bird {
    fly();
    layEggs();
}
interface Fish {
    swim();
    layEggs();
}
// Note: if a value is a union type, we can access only the members that are common to all types of the union type.
function getSmallPet() :Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors
Copy the code

declare

Declare is used to declare the existence of the form.

  • declare var/let/constA variable used to declare the world.
  • declare functionUsed to declare global methods (functions)
  • declare classUsed to declare a global class
  • declare namespaceUsed to declare namespaces
  • declare moduleUsed to declare modules

Tool type

Partial

Partial can quickly make properties defined in an interface type optional

type Partial<T> = {
    [P inkeyof T]? : T[P]; };Copy the code

Use TS to develop the React component

// pages/list/table-list/index.tsx
import React, { useState, useRef } from 'react';
import ProTable, { ProColumns, ActionType } from '@ant-design/pro-table';

interface TableListProps {
  ...
}
// const TableList = (props: TableListProps) => {equivalent to the following
const TableList: React.FC<TableListProps> = (props) = > {
  const [createModalVisible, handleModalVisible] = useState<boolean> (false);
  const [stepFormValues, setStepFormValues] = useState({});
  const actionRef = useRef<ActionType>();
/* note: 1.React.FC refers to the React function component; TableListProps Specifies the type of the constraint; 2. Advantages of using React.FC: Children are implied in the parameters of the function (props); 3. When using React.FC, its default property must be the optional */ property
Copy the code
/ / class components: (source code:. / pages/account/center/index. The TSX)
import { RouteChildrenProps } from 'react-router';

interface CenterProps extends RouteChildrenProps {
  dispatch: Dispatch<any>;
  currentUser: Partial<CurrentUser>;
  currentUserLoading: boolean;
}
interface CenterState {
  newTags: TagType[]; tabKey? :'articles' | 'applications' | 'projects'; inputVisible? :boolean; inputValue? :string;
}

class Center extends Component<CenterProps.CenterState> {
  // Initialize the state, constraining state with the CenterState generic variable above
  state: CenterState = {
    newTags: [].inputVisible: false.inputValue: ' '.tabKey: 'articles'};

S-state type; * /

Copy the code
// HelloClass.tsx
import React, { Component } from 'react';
import { Button } from 'antd';

interface Greeting {
    name: string; firstName? :string; lastName? :string;
}
interface HelloState {
    count: number
}

class HelloClass extends Component<Greeting.HelloState> {
    state: HelloState = {
        count: 0
    }
    static defaultProps = {
        firstName: ' '.lastName: ' '
    }
    render() {
        return (
          <>
            <p>You clicked {this.state.count} times</p>
            <Button onClick={()= > {this.setState({count: this.state.count + 1})}}>
                Hello {this.props.name}
            </Button>
          </>)}}export default HelloClass;

// HelloHOC.tsx
/** Introduce TS generic constraints on high-order components -- this high-order component can add loading state; * 1. Specify the WrappedComponent type as the react pre-defined reference type (react.ponentType); * 2. Generic interfaces need to pass in generic variables; React.componenttype 

, P - indicates the type of the property of the wrapped component; * 3. Transform higher-order functions into generic functions; * 4. Constrain Component types with generic functions and constrain Component property types; * /

import React, { Component } from 'react'; import HelloClass from './HelloClass'; interface Loading { loading: boolean } function HelloHOC<P> (WrappedComponent: React.ComponentType<P>) { return class extends Component<P & Loading> { // Use crossover types to make wrapped components have Loading properties render() { const{ loading, ... props } =this.props; return loading ? <div>Loading...</div> : <WrappedComponent { . props as P} / >; }}}export default HelloHOC(HelloClass); // index.tsx import React from 'react'; import ReactDOM from 'react-dom'; import HelloHOC from './components/HelloHOC'; ReactDOM.render( <HelloHOC name="TypeScript" loading={true} />.document.querySelectorAll('.app') [0]);// Note: After the HelloClass component is wrapped, its default properties are not passed to higher-level components, so it needs to be set to optional; Copy the code
import React, { useState, useEffect } from 'react';
import { Button } from 'antd';

interface Greeting {
    name: string;
    firstName: string;
    lastName: string;
}

const HelloHooks = (props: Greeting) = > {
    const [count, setCount] = useState(0);
    // useState is implemented as a generic function. You can add generic parameters to it to constrain the type of the state, using union types
    const [text, setText] = useState<string | null> (null);

    useEffect(() = > {
        if (count > 5) {
            setText('Take a break');
        }
    }, [count]);

    return (
        <>
            <p>You clicked {count} times {text}</p>
            <Button onClick={()= > {setCount(count + 1)}}>
                Hello {props.name}
            </Button>
        </>
    )
}

HelloHooks.defaultProps = {
    firstName: ' '.lastName: ' '
}

export default HelloHooks;
Copy the code

Type checking mechanism

The principles and behaviors of TypeScript compiler type checking.

Role: assist development, improve development efficiency.

  • Type inference
    • Instead of specifying the type of a variable (the return value type of a function), TypeScript can automatically infer its type based on certain rules.
    • Type assertion is used when you clearly know the context and do not need TS type inference.
  • Type compatibility
    • When one type Y can be assigned to another type X, we can say that type X is compatible with type Y;
    • X compatible Y: X (target type) =Y (source type)
  • Type of protection

The appendix

1. TypeScript vs. JS

  • TypeScript is a superset of JS that extends its syntax so that existing JavaScript code works with TypeScript without modification, and TypeScript provides compile-time static type checking through type annotations.

  • TypeScript processes existing JS code and only compiles TypeScript code within it.

2. TypeScript versus object orientation

Object orientation is a way of understanding and abstracting the real world.

TypeScript is an object-oriented programming language.

Object orientation has two main concepts: objects and classes.

  • Object: An object is an instance of a class, with state and behavior. For example, a dog is an object whose states are: color, name, breed; Behaviors include: wagging tail, barking, eating, etc.
  • Class: A class is a template that describes the behavior and state of a class of objects.
  • Methods: Methods are the implementation steps of a class’s operations.

Refer to the article

  1. Use TypeScript elegantly in React
  2. React + TypeScript practices
  3. Summarize the application experience of TypeScript in project development