03- 在React中使用TypeScript

139 阅读2分钟

在React中使用TypeScript

1. 创建react应用

create-react-app 默认支持TS 添加template typescript 就行

网址:create-react-app.bootcss.com/docs/gettin…

npx create-react-app react-ts-basic --template typescript

2. 关键文件

1. react-app-env.d.ts :React项目默认的类型声明文件

三斜线指令 : 指定依赖的其他类型声明文件,types的值 表示依赖的类型声明文件包的名称

相当于其他引入类型声明文件
/// <reference types="react-scripts" />

// 声明加载资源
declare module '*.module.sass' {
  const classes: {readonly [key:string]:string};
  export default classes
}
// 声明加载资源
declare module '*.jpg' {
  const src:string;
  export default src
}
  • TS会自动加载.d.ts 文件,以提供类型声明在tsconfig.json文件中
{
  // 表示在src文件夹里面所有的类型声明文件 会自动加载
  "include": ['src']
}

2. tsconfig.json 指定TS的编译选项(比如,编译时是否移除注释)

{
  "complerOptions": {
   	// 指定生成代码的语言版本
    "target": "es5",
    // 指定要包含在编译中的library
    "lib": [
      "dom", // 比如dom 表示dom所有的类型都提供了
      "dom.iterable",
      "esnext"
    ],
    // 允许ts编译器编译js文件
    "allowJs": true,
    // 跳过声明文件的类型检查
    "skipLibCheck": true,
    // es模块 互操作 ,屏蔽ESModule 和 CommonJS 之间的差异
    "esModuleInterop": true, // 库用的是CommonJS 但是也可以用ESModule导入
    // 允许通过 import x from 'y' 即使模块没有显式指定 default
    "allowSyntheticDefaultImports": true,
    // 严格模式
    "strict": true,
    // 对文件名强制区分大小写
    "forceConsistentCasingInFileNames": true,
    // 为switch 语句启用错误报告
    "noFallthroughCasesInSwitch": true,
    // 生成代码的模块化标准
    "module": "esnext", // 最新的es模块化标准
    // 模块解析(查找)策略
    "moduleResolution": "node", // 找一个文件按照node方式查找
    // 允许导入扩展名为.json的模块
    "resolveJsonModule": true,
    // 是否将没有 import/export 的文件视为旧(全局而非模块化)脚本文件
    "isolatedModules": true,
    // 不生成JS文件(只进行类型检查)
    "noEmit": true,
    // 指定 jsx 编译成什么形式
    "jsx": "react-jsx"
  }
  // 指定允许 ts 处理的目录
  "include": ['src']
}

3. React 中常用的类型

  • React项目是通过@types/react、@types/react-dom 类型声明包,来提供类型

1. 函数组件的类型以及组件的属性

import ReactDOM from "react-dom"
import { FC } from 'react'

/**
	函数组件
*/
type Props = {name:string,age?:number}

// 正常
const Hello: FC<Props> = ({name,age}) => (
	<div>您好,我叫:{name},我{age}岁了</div>
)
Hello.defaultProps = {
  age:18
}


// 简化
const Hello = ({name,age = 18}: Props) => (
	<div>您好,我叫:{name},我{age}岁了</div>
)


const App = () =>   <div>
                        <Hello name ='jirongliang' />
                    </div>
ReactDOM.render(<App />,document.getElementById('root'))

2. 事件绑定和事件对象

import ReactDOM from "react-dom"
import { FC } from 'react'

const Hello = ({name,age = 18}: Props) => (
  const onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  	console.log('赞!',e.currentTarget);
	}

	const onChange = (e:React.ChangeEvent<HTMLInputElement>) =>{
    console.log(e.target.value);
  }
	<div>您好,我叫:{name},我{age}岁了</div>
  <button onClick={onClick}>电子</button>
	<input onChange={onChange}></input>
)


const App = () => <div>
										<Hello name ='jirongliang' />
									</div>
ReactDOM.render(<App />,document.getElementById('root'))

3. class组件类型

import ReactDOM from "react-dom"
import React from 'react'

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

//                									为setState指定的类型
class Hello extends React.Component<Props,State>{
  
  // 重新指定一次
  state:State = {
    count: 0
  }
  
  onIncrement = ()=>{
    this.setState({
      count: this.state.count + 1
    })
  }
} 
const App = () => <div>
                        <Hello message ='jirongliang' />
                        <button onClick={this.onIncrement}>+1</button>
                  </div>
ReactDOM.render(<App />,document.getElementById('root'))