千家信息网

React项目怎么从Javascript到Typescript

发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,本篇内容介绍了"React项目怎么从Javascript到Typescript"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家
千家信息网最后更新 2025年01月21日React项目怎么从Javascript到Typescript

本篇内容介绍了"React项目怎么从Javascript到Typescript"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

开始迁移

在开始迁移之前,我要说点题外话,本篇文章仅是记录我在迁移过程中遇到的问题以及我是如何解决的,并不会涉及typescript的教学。所以大家在阅读本篇文章之前,一定要对typescript有一个基础的认识,不然你读起来会非常费力。

环境调整

由于Typescript是Javascript的超集,它的很多语法浏览器是不能识别的,因此它不能直接运行在浏览器上,需要将其编译成JavaScript才能运行在浏览器上,这点跟ES6需要经过babel编译才能支持更多低版本的浏览器是一个道理。

tsconfig.json

首先我们得装一个typescript,这就跟我们在用babel前需要先装一个babel-core是一个道理。

yarn global add typescript

这条命令是将typescript安装在全局,其实我个人建议是装在项目目录下的,因为每个项目的typescript版本是不完全一样的,装在全局容易因为版本不同而出现问题。但是后面我要执行tsc命令,所以我装在了全局。***的情况就是全局和项目都装一个,但是如果你把tsc命令放在package.json中的script中去用的话,那么在项目里装就够了。接下来我们执行如下命令生成tsconfig.json,这玩意就跟.babelrc是一个性质的。

tsc --init

执行完之后,你的项目根目录下便会有一个tsconfig.json这么一个东西,但是里面会有很多注释,我们先不用管他的。

webpack

安装ts-loader用于处理ts和tsx文件,类似于babel-loader。

yarn add ts-loader -D

相应的webpack需要加上ts的loader规则:

module.exports = {      //省略部分代码...      module: {          rules: [              {                  test:/\.tsx?$/,                  loader:'ts-loader'              }              //省略部分代码...          ]      }      //...省略部分代码  }

之前用javascript的时候,可能有人不使用.jsx文件,整个项目都是用的.js文件,webapck里面甚至都不配.jsx的规则。但是在typescript项目中想要全部使用.ts文件这就行不通了,会报错,所以当用到了jsx的用法的时候,还是得乖乖用.tsx文件,因此这里我加入了.tsx的规则。

删除babel

关于babel这块,网上有不少人是选择留着的,理由很简单,说是为了防止以后会使用到JavaScript,但是我个人觉得是没有必要留着babel。因为我们整个项目里面基本上只有使用第三方包的时候才会用到javascript,而这些第三方包基本上都是已经编译成了es5的代码了,不需要babel再去处理一下。而业务逻辑里面用javascript更是不太可能了,因为这便失去了使用typescript的意义。综上所述,我个人觉得是要删除babel相关的东西,降低项目复杂度。但是有一个例外情况:。

当你用了某些babel插件,而这些插件的功能恰巧是typescript无法提供的,那你可以保留babel,并且与typescript结合。

文件名调整

整个src目下所有的.js结尾的文件都要修改文件名,使用到jsx语法的就改成.tsx文件,未使用的就改成.ts文件,这块工作量比较大,会比较头疼。另外改完之后文件肯定会有很多标红的地方,不要急着去改它,后面我们分类统一去改。

解决报错

webpack入口文件找不到

由于我们在做文件名调整的时候,把main.js改成main.tsx,因此webpack的入口文件要改成main.tsx。

module.exports = {      //省略部分代码...      entry: {          app: './src/main.tsx'      },      //省略部分代码...  }

提示不能使用jsx的语法

这个解决很简单,去tsconfig配置一下即可。

{     "compilerOptions":{          "jsx": "react"     }  }

jsx这个配置项有三个值可选择,分别是"preserve","react-native"和"react"。在preserve和react-native模式下生成代码中会保留JSX以供后续的转换操作使用(比如:Babel)。另外,preserve输出文件会带有.jsx扩展名,而react-native是.js拓展名。react模式会生成React.createElement,在使用前不需要再进行转换操作了,输出文件的扩展名为.js。

模式输入输出输出文件扩展名
preserve
.jsx
react
React.createElement("div").js
react-native
.js

webpack里面配置的alias无法解析

module.exports = {      //省略部分代码...      resolve: {          alias:{            '@':path.join(__dirname,'../src')          }          //省略部分代码...          },      //省略部分代码...     }

这里需要我们额外在tsconfig.json配置一下。

{      "compilerOptions":{          "baseUrl": ".",          "paths": {            "@/*":["./src/*"]          }       }  }

具体如何配置,请看typescript的文档,我就不展开介绍了,但是要注意的是baseUrl和paths一定要配合使用。

https://www.tslang.cn/docs/ha...

无法自动添加拓展名而导致找不到对应的模块

原先我们在webpack里是这么配置的:

module.exports = {      //省略部分代码...       resolve: {          //省略部分代码...           extensions: ['.js', '.jsx', '.json']      },      //省略部分代码...   }

但是我们项目里所有.js和.jsx的文件都改成了.ts和.tsx文件,因此配置需要调整。

{      //省略部分代码...       resolve: {          //省略部分代码...           extensions: ['.ts','.tsx','.js', '.jsx', '.json']      },      //省略部分代码...   }

Could not find a declaration file for module '**'

这个比较简单,它提示找不到哪个模块的声明文件,你就装个哪个模块的就好了,安装格式如下:

yarn add @types/**

举个?,如果提示Could not find a declaration file for module 'react',那你应该执行如下命令:

yarn add @types/react

这个仅限于第三方包,如果是项目自己的模块提示缺少声明文件,那就需要你自己写对应的声明文件了。比如你在window这个全局对象上挂载了一个对象,如果需要使用它的话,就需要做一下声明,否则就会报错。至于具体怎么写,这得看typescript的文档,这里就不展开说明了。

https://www.tslang.cn/docs/ha...

Cannot find type definition file for '**'

这些并没有在我们的业务代码里直接用到,而是第三方包用到的,遇到这种情况,需要检查一下tsconfig.json中的typeRoots这个配置项有没有配置错误。一般来说是不用配置typeRoots,但是如果需要加入额外的声明文件路径,就需要对其进行修改。typeRoots是有一个默认值,有人会误以为这个默认值是"["node_modules"]",因此会有人这样配置:

{      "compilerOptions":{          "typeRoots":["node_modules",...,"./src/types"]      }  }

实际上typeRoots的默认值"["@types"]",所有可见的"@types"包都会在编辑过程中被加载进来,比如"./node_modules/@types/","../node_modules/@types/"和"../../node_modules/@types/"等等都会被加载进来。所以遇到这种问题,你的配置应该改成:

{      "compilerOptions":{          "typeRoots":["@types",...,"./src/types"]      }  }

在实际项目中,@types基本上存在于根目录下的node_modules下,因此这里你可以改成这样:

{      "compilerOptions":{          "typeRoots":["node_modules/@types",...,"./src/types"]      }  }

不支持decorators(装饰器)

typescript默认是关闭实验性的ES装饰器,所以需要在tsconfig.json中开启。

{      "compilerOptions":{          "experimentalDecorators":true      }  }

Module '**' has no default export

提示模块代码里没有"export

default",而你却用"import from "这种默认导入的形式。对于这个问题,我们需要把tsconfig.json配置项"allowSyntheticDefaultImports"设置为true。允许从没有设置默认导出的模块中默认导入。不过不必担心会对代码产生什么影响,这个仅仅为了类型检查。

{      "compilerOptions":{          "allowSyntheticDefaultImports":true      }  }

当然你也可以使用"esModuleInterop"这个配置项,将其设置为true,根据"allowSyntheticDefaultImports"的默认值,如下:

module === "system" or --esModuleInterop

对于"esModuleInterop"这个配置项的作用主要有两点:

  • 提供__importStar和__importDefault两个helper来兼容babel生态

  • 开启allowSyntheticDefaultImports

对于"esModuleInterop"和"allowSyntheticDefaultImports"选用上,如果需要typescript结合babel,毫无疑问选"esModuleInterop",否则的话,个人习惯选用"allowSyntheticDefaultImports",比较喜欢需要啥用啥。当然"esModuleInterop"是最保险的选项,如果对此拿捏不准的话,那就乖乖地用"esModuleInterop"。

无法识别document和window这种全局对象

遇到这种情况,需要我们在tsconfig.json中lib这个配置项加入一个dom库,如下:

{      "compilerOptions":{          "lib":[              "dom",              ...,              "esNext"          ]      }  }

文件中的标红问题

关于这个问题,我们需要分两种情况来考虑,***种是.ts的文件,第二种是.tsx文件。下面来看一下具体是哪些注意的点(Ps:以下提到的注意的点并不能完全解决文件中标红的问题,但是可以解决大部分标红的问题):

***种:.ts文件

这种文件在你的项目比较少,比较容易处理,根据实际情况去加一下类型限制,没有特别需要讲的。

第二种:.tsx文件

这种情况都是react组件了,而react组件又分为无状态组件和有状态组件组件,所以我们分开来看。

无状态组件

对于无状态组件,首先得限制他是一个FunctionComponent(函数组件),其次限制其props类型。举个?:

import React, { FunctionComponent, ReactElement } from 'react';  import {LoadingComponentProps} from 'react-loadable';  import './style.scss';  interface LoadingProps extends LoadingComponentProps{    loading:boolean,    children?:ReactElement  }  const Loading:FunctionComponent = ({loading=true,children})=>{    return (      loading?
:children ) } export default Loading;

其中你要是觉得FunctionComponent这个名字比较长,你可以选择用类型别名"SFC"或者"FC"。

有状态组件

对于有状态组件,主要注意三点:

  1. 鸿蒙官方战略合作共建--HarmonyOS技术社区

  2. props和state都要做类型限制

  3. state用readonly限制"this.state=**"的操作

  4. 对event对象做类型限制

import React,{MouseEvent} from "react";  interface TeachersProps{    user:User  }  interface TeachersState{    pageNo:number,    pageSize:number,    total:number,    teacherList:{      id: number,      name: string,      age: number,      sex: number,      tel: string,      email: string    }[]  }  export default class Teachers extends React.PureComponent {      readonly state = {          pageNo:1,          pageSize:20,          total:0,          userList:[]      }      handleClick=(e:MouseEvent)=>{          console.log(e.target);      }      //...省略部分代码      render(){          return 
点击我
} }

实际项目里,组件的state可能会有很多值,如果按照我们上面这种方式去写会比较麻烦,所以可以考虑一下下面这个简便写法:

import React,{MouseEvent} from "react";  interface TeachersProps{    user:User  }  const initialState = {    pageNo:1,    pageSize:20,    total:0,    teacherList:[]  }  type TeachersState = Readonly  export default class Teachers extends React.PureComponent {      readonly state = initialState      handleClick=(e:MouseEvent)=>{          console.log(e.target);      }      //...省略部分代码      render(){          return 
点击我
} }

这种写法会简便很多代码,但是类型限制效果上明显不如***种,所以这种方法仅仅作为参考,可根据实际情况去选择。

Ant Design丢失样式文件

当我们把项目启动起来之后,某些同学的页面可能会出现样式丢失的情况,如下:

打开控制台,我们发现Ant Design的类名都找不到对应的样式:

出现这种情况是因为我们把babel删除之后,用来按需加载组件样式文件的babel插件babel-plugin-import也随着丢失了。不过typescript社区有一个babel-plugin-import的Typescript版本,叫做"ts-import-plugin",我们先来安装一下:

yarn add ts-import-plugin -D

这个插件需要结合ts-loader使用,所以webpack配置中需要做如下调整:

const tsImportPluginFactory = require('ts-import-plugin')  module.exports = {      //省略部分代码...      module:{          rules:[{              test: /\.tsx?$/,              loader: "ts-loader",              options: {                  transpileOnly: true,//(可选)                  getCustomTransformers: () => ({                    before: [                      tsImportPluginFactory({                          libraryDirectory: 'es',                          libraryName: 'antd',                          style: true                      })                    ]                  })              }          }]      }      //省略部分代码...  }

这里要注意一下transpileOnly: true这个配置,这是个可选配置,我建议是只有大项目中才加这个配置,小项目就没有必要了。由于typescript的语义检查器会在每次编译的时候检查所有文件,因此当项目很大的时候,编译时间会很长。解决这个问题的最简单的方法就是用transpileOnly: true这个配置去关闭typescript的语义检查,但是这样做的代价就是失去了类型检查以及声明文件的导出,所以除非在大项目中为了提升编译效率,否则不建议加这个配置。

配置完成之后,你的浏览器控制台可能会报出类似下面这个错误:

出现这个原因是因为你的typescript配置文件tsconfig.json中的module参数设置不对,两种情况会导致这个问题:

  • module设置成了"commonjs"

  • target设置"ES5"但是并未设置module(当target不为"ES6"时,module默认为"commonjs")

解决这个办法就是把module设置为"esNext"便可解决这个问题。

{      "compilerOptions":{          "module":"esNext"      }  }

可能会有小伙们说设置成"ES6"或者"ES2015"也是可以的,至于我为什么选择"esNext"而不是"ES6"或者"ES2015",主要原因是设置成"ES6"或者"ES2015"之后,就不能动态导入了,因为项目使用了react-loadable这个包,要是设置成"ES6"或者"ES2015"的话,会报如下这个错误:

typescript提示我们需要设置成"commonjs"或者"ESNext"才可动态导入,所以保险起见,我是建议大家设置成ESNext。完成之后我们的页面就可以正常显示了。

说到module参数,这里要再多提一嘴说一下moduleResolution这个参数,它决定着typescript如何处理模块。当我们把module设置成"esNext"时,是可以不用管moduleResolution这个参数,但是大家项目里要是设置成"ES6"的话,那就要设置一下了。先看一下moduleResolution默认规则:

module === "AMD" or "System" or "ES6" ? "Classic" : "Node"

当我们module设置为"ES6"时,此时moduleResolution默认是"Classic",而我们需要的是"Node"。为什么要选择"node",主要是因为node的模块解析规则更符合我们要求,解析速度会更快,至于详情的介绍,可以参考Typescript的文档。

"React项目怎么从Javascript到Typescript"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

文件 代码 配置 项目 部分 情况 组件 问题 模块 类型 限制 全局 实际 时候 状态 提示 检查 编译 选择 命令 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 通信网络安全的攻击 资助信息网络安全管理制度 自己搭建国外服务器违法吗 万润软件开发 网络安全需求的具体内容 永煊互联网科技有限公司 河南推广软件开发诚信服务 sql数据库同步配置 蓝盟网络安全软件 东南大学网络安全技术研究院 江苏网络技术与新媒体大学 数据库冲突什么意思 福建服务器回收公司云主机 r星服务器为什么总是提示更新 随着手机网络技术的发展 有关手机品牌的数据库 数据库用什么索引 天津正规软件开发服务价格优惠 新神魔大陆服务器寻宝地宫在哪里 四年级网络安全手抄报写什么 怎么查询服务器是否连接外网 奉贤区软件开发案例 软件开发法律咨询 网络安全主题班会20演讲稿 软件开发需不需要学c语言 服务器前面接核心交换机吗 服务器 报价单 学习嵌入式软件开发该学习什么 自学网络安全工程 随着手机网络技术的发展
0