《十三》React 项目中使用 TypeScript

在 React 项目中使用 TypeScript:

  1. 可以执行 create-react-app 项目名 --template typescript 命令来新建一个基于 TypeScript 的 React 项目。

    需要保留默认的 react-app-env.d.ts 文件,是 React 默认提供的类型声明文件。

  2. 也可以在现有的 React 项目中执行 npm install --save typescript @types/react @types/react-dom 来使现有 React 项目支持 TypeScript。

    .js 后缀的文件需要改为 .ts 后缀。
    .jsx 后缀的文件需要改成 .tsx 后缀。

函数式组件的类型约束:

对 props 的类型约束:

可以直接对 props 进行类型约束。

import React from 'react'
import type { ReactNode }  from 'react'

interface IProps {
  id: number,
  count: number,
  // 使用 React 提供的 ReactNode 来对 props.children 进行类型约束
  children?: ReactNode,
}

// 对 props 进行类型约束
const Home = (props: IProps) => {
  return <div>Home</div>
}

export default Home

也可以使用泛型函数来对 props 进行类型约束。这种方式使用更多。

import React from 'react'
import type { ReactNode }  from 'react'

interface IProps {
  id: number,
  count: number,
  // 使用 React 提供的 ReactNode 来对 props.children 进行类型约束
  children?: ReactNode,
}

// 使用 React 提供的 React.FunctionComponent(可以简写为React.FC) 来对函数式组件进行类型约束,然后使用泛型来对 props 进行类型约束
const Home: React.FC<IProps> = () => {
  return <div>Home</div>
}

export default Home

这两种写法是有区别的: 如果直接对 props 进行类型约束,此时 TS 只知道 Home 是个函数;但是如果使用泛型函数来对 props 进行类型约束,此时 TS 知道 Home 是个函数式组件,编写会有更友好的提示,更推荐。

可以看到,ReactNode 是很多类型的联合类型。
请添加图片描述

对 State 的类型约束:

import React, {useState} from 'react'

interface IList {
  name: string,
  age: number,
}

const Home = () => {
  // 对 state 中的 list 进行类型约束
  const [list,setList] = useState<IList[]>([])

  return (
    <div>
      {list.map(item => <div>{item.name}-{item.age}</div>)}
    </div>
  )
}

export default Home

类组件的类型约束:

import React from 'react' 
import type {ReactNode} from 'react'

interface IProps = {
	name: string,
}
interface IState = {
	age: number
}

// 对 props 和 state 进行类型约束
class Home extends React.Component<IProps, IState> {
	state: State = {
		age: 20,
	}

	// 约束 render() 函数返回值是 ReactNode 类型
	render(): ReactNode {
		return (
			<div>{this.props.name}今年{this.state.age}岁!</div>
		)
	}
}

export default Home

路由的类型约束:

import React from 'react'
import {Navigate} from 'react-router-dom'
import type {RouteObject} from 'react-router-dom'
const Home = React.lazy(() => import('src/pages/home'))
const About = React.lazy(() => import('src/pages/about'))

// 使用 React-Router 提供的 RouteObject 作为路由的类型约束
const routes: RouteObject[] = [
  {
    path: '/',
    element: <Navigate to='/home' />
  },
  {
    path: '/home',
    element: <Home/>
  },
  {
    path: '/about',
    element: <About/>
  },
]
export default routes

Redux 状态管理的类型约束:

以在函数式组件中使用的 Hook 为例。

import {configureStore} from '@reduxjs/toolkit'
import counterReducer from './reducers/counter'
import {useSelector, useDispatch} from 'react-redux'
import type {TypedUseSelectorHook} from 'react-redux'

const store = configureStore({
  reducer: {
    counter: counterReducer,
  }
})

// 对 store.state 进行类型约束,否则的话,在组件中使用的时候会报错提示
// 1. 获取 store.getState() 函数的类型
type GetStateFnType = typeof store.getState
// 2. 获取 store.getState() 函数返回值的类型,也就是 store.state 的类型。获取到 state 的类型后当然可以直接在组件中使用,但是每个组件都需要写一遍很麻烦,因此可以使用下面的方式让 TS 自动推导出
type GetStateReturnType = ReturnType<GetStateFnType>
// 3. 定义一个新的 useSelector Hook,并且指定其类型。在组件中不再使用 useSelector 而是使用 useAppSelector,就可以自动推导出第一个函数参数中的 state 参数的类型
export const useAppSelector: TypedUseSelectorHook<GetStateReturnType> = useSelector

// 1. 获取 store.dispatch 的类型
type DispatchType = typeof store.dispatch
// 2. 定义一个新的 useDispatch Hook,并且指定其类型。在组件中不再使用 useDispatch 而是使用 useAppDispatch。其实封不封装都可以,只是为了统一管理,没有什么额外的用处
export const useAppDispatch: () => DispatchType = useDispatch

export default store

设置路径别名:

在基于 TypeScript 的 React 项目中想要设置路径别名,既需要配置 TypeScript 使其在编译阶段能正确地解析别名,也需要配置 Webpack 使其在构建阶段能正确地解析别名。

  1. 配置 TypeScript 使其在编译阶段能正确地解析别名。
    // tsconfig.json
    {
    	...
    	"compilerOptions": {
    		// 指定 TypeScript 模块解析的根路径。当使用相对路径导入模块时,TypeScript 会以 baseUrl 为基准来解析这些路径。
    		"baseUrl": ".",
    		// 创建模块的映射关系,可以将特定的模块名映射到实际的文件路径。
    	    "paths": {
    	      "@/*": ["src/*"]
    	    }
    	}
    }
    
  2. 配置 Webpack 使其在构建阶段能正确地解析别名 。
    // craco.config.js。一般使用 craco 在 React 项目中配置 Webpack,而不是直接弹出 React 中的 Webpack 配置
    const path = require('path')
    
    module.exports = {
      webpack: {
        //配置别名
        alias: {
          //使用 @ 代表 src 文件所在路径
          '@': path.resolve(__dirname, 'src')
        }
      }
    }
    
  3. 在项目中导入模块时,就可以使用 @ 来替代 src 文件夹的路径了。
    // index.tsx
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from '@/App';
    
    const root = ReactDOM.createRoot(
      document.getElementById('root') as HTMLElement
    );
    root.render(
      <App />
    );
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值