从 js 重构为 tsx
Posted
技术标签:
【中文标题】从 js 重构为 tsx【英文标题】:Refactoring from js to tsx 【发布时间】:2021-06-17 17:12:54 【问题描述】:在 React 中我正在尝试将 js 组件重写为 tsx 组件。因此,我只是将 PropTypes 转换为 TypeScript“类型”。刚开始使用 TS,我产生了大量错误“不存在”(ts2339)和“类型缺失”(ts2741)
我的旧 (js) 文件:
import React from "react";
import PropTypes from "prop-types";
import
Dialog,
DialogTitle,
DialogContent,
Typography,
Tooltip,
IconButton,
List,
ListItem,
ListItemText,
from "@material-ui/core";
import makeStyles from "@material-ui/core/styles";
import Close as CloseIcon from "@material-ui/icons";
const useStyles = makeStyles((theme) => (
closeButton:
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
,
));
function AboutDialog(props)
const classes = useStyles();
const dialogProps = props.dialogProps;
const user = props.user;
const version = process.env.REACT_APP_VERSION;
if (!user && !version)
return null;
return (
<Dialog fullWidth maxWidth="xs" ...dialogProps>
<DialogTitle disableTypography>
<Typography variant="h6">
About process.env.REACT_APP_TITLE
</Typography>
<Tooltip title="Close">
<IconButton
className=classes.closeButton
onClick=dialogProps.onClose
>
<CloseIcon />
</IconButton>
</Tooltip>
</DialogTitle>
<DialogContent>
<List disablePadding>
version && (
<ListItem>
<ListItemText primary="Version" secondary=version />
</ListItem>
)
user && (
<ListItem>
<ListItemText primary="UID" secondary=user.uid />
</ListItem>
)
</List>
</DialogContent>
</Dialog>
);
AboutDialog.propTypes =
dialogProps: PropTypes.object.isRequired,
user: PropTypes.object,
;
export default AboutDialog;
我的新 (tsx) 文件:
import React from "react";
import
Dialog,
DialogTitle,
DialogContent,
Typography,
Tooltip,
IconButton,
List,
ListItem,
ListItemText,
from "@material-ui/core";
import makeStyles from "@material-ui/core/styles";
import Close as CloseIcon from "@material-ui/icons";
const useStyles = makeStyles((theme) => (
closeButton:
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
,
));
type AboutDialogProps =
dialogProps: object;
user?: object;
;
const AboutDialog: React.FC<AboutDialogProps> = (props) =>
const classes = useStyles();
const dialogProps = props.dialogProps;
const user = props.user;
const version = process.env.REACT_APP_VERSION;
if (!user && !version)
return null;
return (
<Dialog fullWidth maxWidth="xs" ...dialogProps>
<DialogTitle disableTypography>
<Typography variant="h6">
About process.env.REACT_APP_TITLE
</Typography>
<Tooltip title="Close">
<IconButton
className=classes.closeButton
onClick=dialogProps.onClose
>
<CloseIcon />
</IconButton>
</Tooltip>
</DialogTitle>
<DialogContent>
<List disablePadding>
version && (
<ListItem>
<ListItemText primary="Version" secondary=version />
</ListItem>
)
user && (
<ListItem>
<ListItemText primary="UID" secondary=user.uid />
</ListItem>
)
</List>
</DialogContent>
</Dialog>
);
;
export default AboutDialog;
错误 1: 类型 ' children: Element[]; 中缺少属性 'open';全宽:真;最大宽度:“xs”; ' 但在类型 'DialogProps'.ts(2741) 中是必需的 Dialog.d.ts(88, 3): 'open' 在这里声明。
错误 2: 'object'.ts(2339) 类型上不存在属性 'onClose'
错误 3: 类型 'object'.ts(2339) 上不存在属性 'uid'
试图修复其他组件中的内容只会产生更多错误。我在这里在概念上无法理解什么? // 你将如何转换/重构它?
从前两个 cmets 修复后更新(3 月 21 日): 从“反应”导入反应;
import
Dialog,
DialogTitle,
DialogContent,
Typography,
Tooltip,
IconButton,
List,
ListItem,
ListItemText,
DialogProps,
from "@material-ui/core";
import makeStyles from "@material-ui/core/styles";
import Close as CloseIcon from "@material-ui/icons";
const useStyles = makeStyles((theme) => (
closeButton:
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1),
,
));
interface User
uid: string;
email: string;
emailVerified: string;
password: string;
displayName: string;
photoURL: string;
disabled: string;
;
interface AboutDialogProps
dialogProps?: DialogProps;
user?: User;
onClose: () => void;
;
const AboutDialog = (props: AboutDialogProps) =>
const classes = useStyles();
const dialogProps = props.dialogProps;
const user = props.user;
const version = process.env.REACT_APP_VERSION;
if (!user && !version)
return null;
return (
<Dialog fullWidth maxWidth="xs" ...dialogProps>
<DialogTitle disableTypography>
<Typography variant="h6">
About process.env.REACT_APP_TITLE
</Typography>
<Tooltip title="Close">
<IconButton
className=classes.closeButton
onClick=dialogProps.onClose
>
<CloseIcon />
</IconButton>
</Tooltip>
</DialogTitle>
<DialogContent>
<List disablePadding>
version && (
<ListItem>
<ListItemText primary="Version" secondary=version />
</ListItem>
)
user && (
<ListItem>
<ListItemText primary="UID" secondary=user.uid />
</ListItem>
)
</List>
</DialogContent>
</Dialog>
);
;
export default AboutDialog;
这会在 IconButton 上引发新错误:
"
没有重载匹配此调用。
重载 1 of 3, '(props: href: string; & color?: Color | undefined; disableFocusRipple?: boolean | undefined; edge?: false | "end" | "start" | undefined; size?: " medium" | "small" | undefined; & ...; & CommonProps<...> & Pick<...>): Element',给出了以下错误。
输入'((事件:,原因:“backdropClick”|“escapeKeyDown”)=> void)| undefined' 不可分配给类型 'MouseEventHandler |不明确的'。
类型 '(event: , reason: "backdropClick" | "escapeKeyDown") => void' 不可分配给类型 'MouseEventHandler'。
重载 2 of 3, '(props: component: ElementType; & color?: Color | undefined; disableFocusRipple?: boolean | undefined; edge?: false | "end" | "start" | undefined; size?:" medium" | "small" | undefined; & ...; & CommonProps<...> & Pick<...>): Element',给出了以下错误。
类型“ children: Element;”中缺少属性“组件”;类名:字符串; onClick: ((事件: , 原因: "backdropClick" | "escapeKeyDown") => void) |不明确的; ' 但在类型 ' component: ElementType; '。
重载 3 个,共 3 个,'(props: DefaultComponentProps
... 并在对话框上: " 类型'孩子:元素[]; 'aria- describeby'?: 字符串 |不明确的; 'aria-labelledby'?: 字符串 |不明确的; disableBackdropClick?: 布尔值 |不明确的; disableEscapeKeyDown?: 布尔值 |不明确的; ... 285 更多 ...;类?:部分<...> |不明确的; ' 不可分配给类型 'DialogProps'。 属性“开放”的类型不兼容。 输入'布尔| undefined' 不可分配给类型 'boolean'。 类型“未定义”不可分配给类型“布尔”。ts(2322) "
【问题讨论】:
此外,可用于将 js 转换为 typescript 的 npm 包似乎下载量很少(例如 react-proptypes-to-typescript 或 react-js-to-ts)。我想很多人在将 js 转换为 ts 时一定有类似的问题,除了自动化之外,你能推荐什么吗? 【参考方案1】:Typescript 是强类型语言。 让我们关注错误:
-
open 是未键入的。
onClose 没有类型。
uid 没有类型。
它是对象,所以我建议创建接口 IOpen:
interface IOpen
children: Array<Element>
fullWidth: boolean;
maxWidth: string
onClose - 可能需要输入:
onClose: () => void
uid - 可能需要类型 - 我看到 uid 是用户 object 内部的 string。所以有可能添加另一个接口:
interface IUser
(...)
uid:string
(...)
在您的情况下,您键入 user like object 是真的 - 但 ts 编译器需要更具体的信息。
【讨论】:
谢谢,我不确定我是否理解 100%。我编辑了上面的文件。 onClose 类型是否正确实现?然后应该从 material-ui 导入接口 IOpen(如上面编辑的解决方案中所做的那样)? 如果它是库的一部分,那么它应该包含它的类型 哈哈 - 欢迎来到打字稿的阴暗面 刚刚通过 materialUI 文档再次实现 TS。它变得更加痛苦:material-ui.com/guides/typescript :) 仍然无法正常工作我认为最好的方法是保留现有的 js(x) 文件并仅将 TS 添加到新组件中......【参考方案2】:在定义类型时,您希望比“对象”更具体一点。 像这样的东西应该可以工作
type User =
uid: string;
//add all the property of your user
;
type AboutDialogProps =
dialogProps: DialogProps; //DialogProps is imported from @material-ui/core
user?: User;
;
【讨论】:
谢谢,这修复了它的一部分,但也产生了一些新的错误。你们一般是怎么做的。这是要重构为 TS 的 25 个文件中的第一个,它需要花费几个小时来阅读错误。我可以将现有文件保留在 JS 中并在新文件中使用 TS 构建吗?如果它们使用旧 JS 文件的一部分并且一切都应该顺利运行,这是否意味着在新文件中简单地定义接口/类型?以上是关于从 js 重构为 tsx的主要内容,如果未能解决你的问题,请参考以下文章
将 d3 js 代码从 v5.16 重构到 v6.6.2,d3.event 重大更改
如何将前端 JS 重构为 Angular 2 以与 PHP MVC 后端完美配合? [关闭]