TypeScript下如何为React中withRouter传入的history对象添加类型检查?
为withRouter包装的子组件的history props添加类型检查的规范实现
我来给你讲讲两种主流场景下的规范实现方式,对应不同的技术栈:
一、TypeScript 项目(推荐,React Router官方支持)
React Router 已经为我们提供了现成的类型定义,直接用官方类型就能保证准确性,不用自己手动拼凑结构。
方法1:使用 RouteComponentProps 完整类型
这个类型包含了 history、location、match 这三个由 withRouter 注入的props,适合需要用到多个路由相关props的场景:
import { RouteComponentProps, withRouter } from 'react-router-dom'; import styles from './ChildComponent.module.css'; import FloatingActionButton from './FloatingActionButton'; import routes from './routes'; // 定义组件props类型 type ChildComponentProps = RouteComponentProps; const ChildComponent = ({ history }: ChildComponentProps) => ( <div className={styles.body}> <div className={styles.cta}> <FloatingActionButton onClick={() => history.push(routes[4].path)}> <span>Click me</span> </FloatingActionButton> </div> </div> ); export default withRouter(ChildComponent);
方法2:只提取 history 属性(更精准)
如果你的组件只用到 history,不需要其他路由props,可以用 Pick 工具类型只提取需要的部分:
import { RouteComponentProps, withRouter } from 'react-router-dom'; import styles from './ChildComponent.module.css'; import FloatingActionButton from './FloatingActionButton'; import routes from './routes'; // 只保留history属性 type ChildComponentProps = Pick<RouteComponentProps, 'history'>; const ChildComponent = ({ history }: ChildComponentProps) => ( <div className={styles.body}> <div className={styles.cta}> <FloatingActionButton onClick={() => history.push(routes[4].path)}> <span>Click me</span> </FloatingActionButton> </div> </div> ); export default withRouter(ChildComponent);
方法3:直接使用 History 类型
也可以单独导入 History 类型来定义props:
import { History, withRouter } from 'react-router-dom'; import styles from './ChildComponent.module.css'; import FloatingActionButton from './FloatingActionButton'; import routes from './routes'; type ChildComponentProps = { history: History; }; const ChildComponent = ({ history }: ChildComponentProps) => ( <div className={styles.body}> <div className={styles.cta}> <FloatingActionButton onClick={() => history.push(routes[4].path)}> <span>Click me</span> </FloatingActionButton> </div> </div> ); export default withRouter(ChildComponent);
二、JavaScript 项目(使用 PropTypes)
如果你的项目还在使用纯JavaScript,可以通过 PropTypes 来做运行时的类型检查,只需要定义你实际用到的方法即可:
import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; import styles from './ChildComponent.module.css'; import FloatingActionButton from './FloatingActionButton'; import routes from './routes'; const ChildComponent = ({ history }) => ( <div className={styles.body}> <div className={styles.cta}> <FloatingActionButton onClick={() => history.push(routes[4].path)}> <span>Click me</span> </FloatingActionButton> </div> </div> ); // 定义props类型检查规则 ChildComponent.propTypes = { history: PropTypes.shape({ push: PropTypes.func.isRequired, // 你用到的push方法必须是函数且必填 // 如果后续用到其他方法,比如replace、goBack,可以按需添加 replace: PropTypes.func, goBack: PropTypes.func, }).isRequired, }; export default withRouter(ChildComponent);
简单总结下:TypeScript场景优先用官方提供的类型,既规范又能获得完整的类型提示;JavaScript场景用PropTypes做运行时校验,只定义用到的属性即可,不用冗余定义整个history对象的所有方法。
内容的提问来源于stack exchange,提问作者Ivin
相关产品推荐
相关产品推荐

