Week 46 Summary - TypeScript

TypaScript

Common types

primitive type

let age:number=20;
let myName:string='xsx'
let isLoading:boolean=false;
let a:null=null;
let b:undefined=undefined;
let s:symbol=Symbol();

array type

let numbers:number[]=[1,2,3];
let numbers2:Array<number>=[1,2,3];

union type

let arr:(number|string)[]=['1','2',1,2];

function type

function add(num1:number,num2:number):number{
    return num1+num2;
}
const add2=(num1:number,num2:number):number=>{
    return num1+num2;
}
optional arguments to the function
function mySlice(start?:number,end?:number):void{
    console.log(`起始索引${start},结束索引${end}`);
}

mySlice();
mySlice(1);
mySlice(1,2);

object type

let person:{name:string;age:number;sayHi():void;greet(name:string):void}={
    name:'jack',
    age:19,
    sayHi(){},
    greet(name){},
}
let person2:{
    name:string
    age:number
    sayHi:()=>void
    greet(name:string):void
}={
    name:'jack',
    age:19,
    sayHi(){},
    greet(name){},
}
optional properties of the object
function myAxios(config:{url:string;method?:string}){
    console.log(config);
}

advanced type

interface

interface IPerson{
    name:string
    age:number
    sayHi():void
}
let person3:IPerson={
    name:'jack',
    age:19,
    sayHi(){}
}
interface inheritance
interface Point2D{
    x:number
    y:number
}
interface Point3D extends Point2D{
    z:number
}
let d2:Point2D={
    x:1,
    y:2
}
let d3:Point3D={
    x:1,
    y:2,
    z:3
}

type alias

type TPerson={
    name:string
    age:number
    sayHi():void
}
let person4:TPerson={
    name:'jack',
    age:19,
    sayHi(){}
}

type assertion

//如果不知道是什么类型的,可以在控制台选中元素,输入console.dir($0)查看。
const aLink = <HTMLAnchorElement>document.getElementById('link')

Interfaces vs Type Aliases

//接口只能给对象起别名,而类型别名可以给任意类型起别名
type NumStr = number | string;

literal type

const str2:'Hello TS' = 'Hello TS'
let age2:18=18
function changeDirection(direction:'up'|'down'|'left'|'right'){
    console.log(direction);
}
changeDirection('up');

Numerical enumeration

//对于数字枚举存在自增长行为,如果你不设置数值,则会从0依次增长。
enum Direction{Up,Down,Left,Right}
enum Direction2{Up=10,Down=22,Left=65,Right=1025}
function changeDirection2(direction:Direction){
    console.log(direction);
}
changeDirection2(Direction.Up)

string enumeration

enum Direction3{
    Up='Up',
    Down='Down',
    Left='Left',
    Right='Right',
}

any type (deprecated)

/*
    不推荐使用any类型,它会让TypeScript变成AnyScript,会失去TypeScript类型保护的优势。

*/
let objans:any={x:0};
objans();
//上述代码执行错误
Implicitly has type any
  1. Declare a variable without providing a type nor a default value
  2. function parameter without type

typeof in TypeScript

//typeof只能查询变量或属性的类型,无法查询其他形式的类型
let p={x:1,y:2};
function formatPoint(point:{x:number,y:number}){}
formatPoint(p);
function formatPoint2(point:typeof p){}
formatPoint2(p);

class class

class Persons{
    ages!:number
    gender='男'
}
const per=new Persons();
class class constructor
class Persons{
    ages!:number
    gender='男'
    constructor(ages:number,gender:string){
        this.ages=ages;
        this.gender=gender
    }
}
const per=new Persons(18,'女');
Instance methods of the class class
class Point{
    x=10
    y=10
    scale(n:number):void{
        this.x*=n;
        this.y*=n;
    }
}
const poi=new Point();
poi.scale(10);
The class class inherits the parent class
class Animal{
    move(){
        console.log('移动');
    }
}
class Dog extends Animal{
    bark(){
        console.log('汪');
    }
}
const dog=new Dog();
The class class implements the interface
interface Singalbe{
    sing():void
}
class Persons2 implements Singalbe{
    sing(): void {
        console.log('sign');
    }
}
class class visibility modifier
  1. public (public, default is public)
class Animal{
    public move(){
        console.log('移动');
    }
}
  1. protected (protected)
//仅对声明的所有类和子类中(非实例对象)可见。
class Animal{
    protected move(){
        console.log('移动');
    }
}
class Dog extends Animal{
    bark(){
        console.log('汪');
        this.move();
    }
}
  1. private (private)
//只在当前类中可见,对实例对象以及子类都不可见
class Animal{
    private move(){
        console.log('移动');
    }
}
class Dog extends Animal{
    bark(){
        console.log('汪');
        this.move();//报错
    }
}
  1. readonly (read-only, not only available in the class class)
/*
用来防止在构造函数之外对属性进行赋值,可以在声明时和constructor里面进行赋值
只可以修饰属性,不能修饰方法
下面代码中如果:number没有写,则age会变成字面量类型,如果再在constructor中改变值会报错。
接口或{}表示的对象类型,也可以使用readonly
*/
class Persons3{
    readonly age:number=18
    constructor(){
        this.age=age;
    }
    setAge(){
        this.age=20//报错
    }
}
interface readi{
    readonly age:18
}
let obji:{readonly age:number}={
    age:18
}

type compatibility

    TypeScript uses a structured type system, also known as duck typing (duck type), if two objects have the same shape, they are considered to belong to the same type.
    In Java and c#, they are marked type systems and will not be judged by having the same shape.

class Pointl{x!:number;y!:number}
class pointl2D{x!:number;y!:number}
const pl:Pointl=new pointl2D();
//在TypeScript看来Pointl和pointl2D是同一类型
Type Compatibility Between Objects

    For object types, if the members of y are at least the same as x, then x is compatible with y (more members can be compatible with fewer).

class pointl2D{x!:number;y!:number}
class pointl3D{x!:number;y!:number;z!:number}
const ppl:Pointl=new pointl3D();
Type Compatibility Between Interfaces
interface Int1{
    x:number
    y:number
}
interface Int2{
    x:number
    y:number
}
interface Int3{
    x:number
    y:number
    z:number
}
let inte1:Int1={x:1,y:2};
let inte2:Int2={x:1,y:2};
let inte3:Int3={x:1,y:2,z:3};
inte1=inte2;
inte2=inte1;
inte1=inte3;
inte3=inte1;//报错
Compatibility between class and interface
interface ic1{
    x:number
    y:number
}
class ic2{
    x!:number
    y!:number
}
let ict:ic1=new ic2();
Compatibility between functions

    Compatibility between functions should consider three aspects.

  1. The number of parameters
        is more compatible with fewer parameters. (Those with fewer parameters can be assigned to those with more parameters)
type F1=(a:number)=>void
type F2=(a:number,b:number)=>void
let f1:F1=(a)=>{};
let f2:F2=(a,b)=>{};
f2=f1;
f1=f2;//报错
  1. Parameter types
        at the same position must be the same (primitive type) or compatible (object type)
type F1=(a:number,b:string)=>void
type F2=(a:number,b:number)=>void
let f1:F1=(a,b)=>{};
let f2:F2=(a,b)=>{};
f2=f1;//报错
interface ic1{
    x:number
    y:number
}
class ic2{
    x!:number
    y!:number
}
type F1=(a:number,b:ic1)=>void
type F2=(a:number,b:ic2)=>void
let f1:F1=(a,b)=>{};
let f2:F2=(a,b)=>{};
f2=f1;
  1. return type
    • If the return value type is a primitive type, the two types must be the same
type F5=()=>string;
type F6=()=>string;
let f5:F5=()=>'1';
let f6:F6=()=>'1';
f6=f5;
- 如果返回值类型是对象类型,此时成员多的可以赋值给成员少的(和对象类型一直)
type F7=()=>{name:string}
type F8=()=>{name:string;age:number}
let f7:F7=()=>{return{
    name:'111'
}};
let f8:F8=()=>{return{
    name:'111',
    age:10
}};
f7=f8;
f8=f7;//报错

&cross type

    Cross type & function is similar to interface inheritance, used to combine multiple types into one type (often used for object types)

interface jio1{name:string}
interface jio2{age:number}
type Jio = jio1&jio2;
let obj:Jio={
    name:'111',
    age:10
}
Comparison of intersection types and interface inheritance
  1. The same point
        can realize the combination of object types.
  2. The difference is that
        when the two methods implement type combination, the methods for handling type conflicts between attributes with the same name are different.
interface A{
    fn(a:number):string
}
interface B extends A{//报错,类型不兼容
    fn(a:string):string
}
interface A{
    fn(a:number):string
}
interface B{
    fn(a:string):string
}
type C = A & B

    For C, we can understand it as the following code

interface A{
    fn(a:number):string
}
interface B{
    fn(a:string):number
}
type C = A & B

class cc implements C{
    fn(a: number): string;
    fn(a: string): number;
    fn(a: unknown): string | number {
        return ''
    }
}

generic

    Generics can allow multiple types such as functions to work together on the premise of protecting type safety, thereby achieving reuse. Example: Implement a function that returns whatever data is input.

function id<Type>(value:Type):Type{
    return value
}
id<number>(10);
id(10);//如果编译器推断的类型不准确,我们必须在括号前声明类型
id<string>(10);//报错
//Type也可以写成别的合法名称
Generic constraints
function id2<Type>(value:Type):Type{
    return value.length//报错
}

    Add generic constraints

  1. Specify a more specific type
function ida<type>(value:type[]):type[]{
    return value.length
}
  1. extendsAdd constraints
interface ILength{length:number};
function ide<type extends ILength>(value:type):type{
    console.log(value.length);
    return value
}
ide([]);
ide('');
ide({length:0,name:'0'});
The case of multiple generic variables

    The keyof keyword takes an object type and produces a union type of its key names (which may be strings or numbers)

function getProp<Type,Key extends keyof Type>(obj:Type,key:Key){
    return obj[key];
}
let objkey={name:'11'};
getProp(objkey,'name');
getProp(objkey,'age');//报错
getProp([],0);
getProp(0,'toString');
generic interface
interface IdFunc<Type>{
    id:(value:Type)=>Type
    ids:()=>Type[]
}
let func1:IdFunc<number>={
    id(value) {
        return value
    },
    ids() {
        return []
    },
}
Arrays are generic interfaces

    You can click to view the forEach source code of the array.

generic class

    The base class Component in React's class component is a generic class, and different components have different props and states.

interface IState{count:number}
interface IProps{maxLength:number}
class InputCount extends React.Component<IProps,IState>{
    state:IState{
        const:0
    }
    render(){
        return <div>{this.props.maxLength}</div>
    }
}

    create generic class

class Generic<NumType>{
    defaultVlaue!:NumType
    add!:(x:NumType,y:NumType)=>NumType
}
const myGen = new Generic<number>()
myGen.defaultVlaue=10
generic utility type

    TypeScript has built-in some commonly used tool types to simplify some common operations in TypeScript.

  1. Partial
        is used to construct (create) a type and set all properties of Type to optional.
interface PropsP{
    id:string
    children:number[]
}
type PartialProps = Partial<PropsP>
class classProps implements PartialProps{
    id!: string;
}
  1. Readonly
        is used to construct a type, and set all the properties of Type to readonly (read-only)
interface PropsR{
    id:string
    children:number[]
}
type ReadonlyProps = Readonly<PropsP>
let rp:ReadonlyProps={
    id:'1',
    children:[]
}
rp.id='2'//报错
  1. Pick
        selects a set of properties from Type to construct a new type.
interface PropsPi{
    id:string
    children:number[]
}
type PickProps = Pick<PropsPi,'id'>
let pp:PickProps={
    id:'1',
    children:[]//报错
}
//PickProps类型中只有id,所以会报错。
  1. Record<Keys,Type>
        constructs an object type, the attribute key is Keys, and the attribute type is Type. Record passes in two type variables, the first indicates which properties the object has, and the second indicates the type of the object's properties.
type RecordObj=Record<'a'|'b'|'c',string[]>
let objRec:RecordObj={
    a:['1'],
    b:['1'],
    c:['1']
}
Index signature type

    When it is impossible to confirm which attributes are in the object or that any number of attributes can appear in the object, the index signature type is used at this time.

interface AnyObject{
    [Key:string]:number
}
let anyobj:AnyObject={
    a:1,
    'b':2,
}
//Key只是一个占位符,可以换成任意合法的变量名称。

mapping type

type PropKeys='x'|'y'|'z'
type Type1={x:number;y:number;z:number}
type Type2={[Key in PropKeys]:number}//映射
//Key只是一个占位符,可以换成任意合法的变量名称
type Props={a:number,b:string,c:boolean}
type Type3={[Key in keyof Props]:number}
Analyze the implementation of the generic tool type Partial
type Partials<T>={
    [P in keyof T]?:T[P]
}
type ParText={a:number;b:string;c:boolean}
type part=Partials<ParText>

index query type

  1. basic use
type Propsi={a:number;b:number;c:number}
type Tyepi=Propsi['a'];
  1. query multiple
type Propsi={a:number;b:number;c:number}
type Tyepi2=Propsi['a'|'b'];
type Tyepi3=Propsi[keyof Propsi];

type declaration file

Two file types in TypeScript

    Almost all JavaScript applications today will introduce many third-party libraries to complete the task requirements. Regardless of whether these third-party libraries are written in TS, they must be compiled into JS code in the end before they can be released to developers. We know that TS provides types, so there are mechanisms such as code hints and type protection. But when you use third-party libraries in project development, you will find that almost all of them have corresponding TS types. How do these types come from? Type declaration files: used to provide type information for existing JS libraries. In this way, when using these libraries in a TS project, just like using TS, there will be code hints, type protection and other mechanisms.

  1. Two file types of TS
    • .ts files
      1. Contains both type information and executable code
      2. Can be compiled into a .js file and then execute the code
      3. Purpose: A place to write program code
  2. Instructions for use of type declaration files
    • .d.ts files
      1. A type declaration file that contains only type information
      2. No .js files will be generated, only used to provide type information
      3. Purpose: Provide type information for js
        ※.ts is a code implementation file; .d.ts is a type declaration file

Type declaration files for third-party libraries

  1. The type declaration file that comes with the library
  2. Provided by DefinitelyTyped

Create your own type specification file

  1. Shared types within a project
        If the same type is used in multiple .ts files, you can create a .d.ts file to provide this type to achieve type sharing.
  • Steps
    1. Create index.d.ts event type declaration file
    2. Create types that need to be shared and use export to export (types in TypeScript can also use import/export to achieve modular functions)
    3. In the .ts file that needs to use the shared type, it can be imported through import (when the .d.ts suffix is ​​imported, it is directly omitted)
  1. Provide type declarations for existing JS files
    1. When migrating JS projects to TS projects, in order to allow existing js files to have type declarations.
    2. Become a library author and create libraries for others to use.
    • Note: .js files can also be used in TypeScript projects. When importing .js files, TypeScript will automatically load .d.ts files with the same name as .js to provide type declarations. The declare keyword: used for type declarations, declaring types for variables that already exist elsewhere (such as .js files) instead of creating a new type.
      1. For type.interface, etc., which are clearly of TS type (only used in TS), the declare keyword can be omitted.
      2. For let.function, which has double meanings (usable in both JS and TS), the declare keyword should be used to clearly specify that it is used for type declaration.

Using TypeScript with React

Use CRA to create a TypeScript-enabled project

    The command to create a project that supports TypeScript: npx create-react-app project name.     Compared with non-TypeScript projects using TypeScript in existing projects , the directory structure mainly changes in the following three ways.

  1. The tsconfig.json configuration file is added to the project root directory: specify TS compilation options (for example, whether to remove comments when compiling).
  2. The file extension for React components becomes: *.tsx.
  3. The react-app-env.d.ts: default type declaration file for React projects has been added to the src directory.
  4. The triple slash directive in the react-app-env.d.ts file specifies other dependent type declaration files, and types indicates the name of the dependent type declaration file package.

TypeScript configuration file tsconfig.json

{
  "compilerOptions": {
    "target": "es6",//生成代码的语言版本
    "lib": [//指定要包含在编译中的library
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,//允许ts编译器编译js文件
    "skipLibCheck": true,//跳过声明文件的类型检查
    "esModuleInterop": true,//es模块互操作,屏蔽ESModule和CommonJS之间的差异
    "allowSyntheticDefaultImports": true,//允许使用import
    "strict": true,//开启严格模式
    "forceConsistentCasingInFileNames": true,//对文件名称强制区分大小写
    "noFallthroughCasesInSwitch": true,//为switch语句启用报错报告
    "module": "esnext",//生成代码的模块化标准
    "moduleResolution": "node",//模块解析(查找)策略
    "resolveJsonModule": true,//允许导入扩展名为.json的模块
    "isolatedModules": true,//是否将没有import/export的文件规为旧(全局而非模块化)脚本文件
    "noEmit": true,//编译时不生产任何文件(只进行类型检查)
    "jsx": "react-jsx"//将指定jsx编译成什么形式
  },
  "include": [//指定允许ts处理的目录
    "src"
  ]
}

Commonly used types in React

    When not using TypeScript, you can use the prop-types library to provide type checking for React components. In TypeScript projects, it is recommended to use TypeScript or Flow to implement component type validation (instead of prop-types)

function component
  1. Component and Property Types
//组件和属性类型
import React,{FC} from 'react';
type Props={name:string;age?:number}
const Hello:FC<Props>=({name,age})=>(
  <div>你好,我叫:{name},我{age}岁了</div>
)
const Hello2=({name,age}:Props)=>(
  <div>你好,我叫:{name},我{age}岁了</div>
)
  1. Default values ​​for component properties (defaultProps)
//属性默认值
import React,{FC} from 'react';
const Hello:FC<Props>=({name,age})=>(
  <div>你好,我叫:{name},我{age}岁了</div>
)
Hello.defaultProps={
  age:18
}
const Hello2=({name,age=18}:Props)=>(
  <div>你好,我叫:{name},我{age}岁了</div>
)
  1. Event Binding and Event Objects
//事件与事件对象
import React from 'react'

export default function Test() {
  function onclick(e:React.MouseEvent<HTMLButtonElement>){
    console.log(e.currentTarget);
  }
  function onchange(e:React.ChangeEvent<HTMLInputElement>){
    console.log(e.target);
    
  }
  return (
    <div>
      <button onClick={onclick}>你点我一下</button>
      <input type="text" onChange={onchange} />
    </div>
  )
}
class component
  1. Components and Types
type State = { count: number }
type Props = { message? :string }
class C1 extends React.Component }// 无props、state
class C2 extends React.Component<Props> {}//有props,无state
class C3 extends React.Component<{}, State> }//无props, 有state
class C4 extends React.Component<Props, State> 年} //有props、state
  1. Component properties and default values
import React, { Component } from 'react'
type Props = { name:string;age?:number }
export default class TestClass extends Component<Props> {
  static defaultProps:Partial<Props>={
    age:14
  }
  render() {
    const {name,age=18} = this.props
    return (
      <div>
        你好,我叫:{name},我{age}岁了
      </div>
    )
  }
}
  1. Status and Events
import React, { Component } from 'react'
type State = { count:number }
export default class TestClass extends Component<{},State> {
  state:State={
    count:0
  }
  add=()=>{
    this.setState({
        count:this.state.count+1
    })
  }
  render() {
    return (
      <div>
        {this.state.count}
        <button onClick={this.add}>+1</button>
      </div>
    )
  }
}

Guess you like

Origin blog.csdn.net/qq_51965698/article/details/125586386