投掷与引用现在越来越多的项目放弃了javascript而选择拥抱typescript,比如大家熟知的ant-design就是其中之一。面对越来越流行的typescript,我们公司今年也逐渐开始拥抱typescript。至于为什么要用打字稿?本文不深入。本文比较全面地介绍了TypeScript,并与Javascript做了对比。看完上面的文章,你会对TypeScript有更深入的了解。此外,您可以在TypeScript和Javascript之间做出更好的选择。在开始迁移之前,我想说一些题外话。本文只记录我在迁移过程中遇到的问题以及我是如何解决的,不涉及typescript的教学。所以在阅读这篇文章之前,你必须对typescript有一个基本的了解,否则你阅读起来会很吃力。环境调整由于Typescript是Javascript的超集,其语法很多浏览器无法识别,所以不能直接在浏览器上运行,需要编译成JavaScript才能在浏览器上运行,需要通过ES6传递babel编译可以支持更多低版本浏览器是个事实。tsconfig.json首先我们要安装一个typescript,这和我们在使用babel之前需要安装一个babel-core是一样的。yarnglobaladdtypescript命令是全局安装typescript。其实我个人比较推荐安装在项目目录下,因为每个项目的typescript版本不完全一样,全局安装容易因为版本不同而出现问题。但是后面想执行tsc命令,所以就全局安装了。最坏的情况是全局和项目都安装一个,但是如果你把tsc命令放在package.json中的脚本中使用,那么在项目中安装就可以了。接下来,我们执行下面的命令生成tsconfig.json,它和.babelrc是同一个性质。执行完tsc--init后,在你的项目根目录下会多出一个tsconfig.json,不过里面会有很多注释,暂且不管。webpack安装了ts-loader来处理ts和tsx文件,类似于babel-loader。yarnaddts-loader-D对应的webpack需要添加tsloader规则:module.exports={//省略部分代码...module:{rules:[{test:/\.tsx?$/,loader:'ts-loader'}//省略部分代码...]}//...省略部分代码}之前使用javascript的时候,有些人可能不会使用.jsx文件,整个项目都使用.js文件,甚至在webapck中都不符合.jsx规则。但是如果你想在typescript项目中使用所有的.ts文件,那是不行的,会报错,所以你在使用jsx用法的时候,还是要乖乖的使用.tsx文件,所以这里我加了.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={//Omitpartofthecode...entry:{app:'./src/main.tsx'},//Omitpartofthecode...}提示jsx的语法不能用过这个方案很简单,去tsconfig配置即可。{"compilerOptions":{"jsx":"react"}}jsx配置项有三个值可以选择,分别是"preserve"、"react-native"和"react"。JSX会保存在preserve和react-native模式下生成的代码中,用于后续的转换操作(eg:Babel)。此外,保留输出文件将具有.jsx扩展名,而react-native具有.js扩展名。react模式会生成React.createElement,使用前无需转换,输出文件后缀为.js。modeinputoutputoutputfileextensionpreserve
.jsxreactReact.createElement("div").jsreact-native.js配置在webpack别名中不能resolvemodule.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:{//Omitsomecode...extensions:['.js','.jsx','.json']},//Omitsomecode...}Butall.jsandThe.jsx文件已更改为.ts和.tsx文件,因此需要调整配置。{//省略一些代码...resolve:{//省略一些代码...extensions:['.ts','.tsx','.js','.jsx','.json']},//省略部分代码...}Couldnotfindadeclarationfileformodule'**'这个比较简单,提示找不到哪个模块的声明文件,你就安装哪个模块,安装格式如下:yarnadd@types/**例如🌰,如果提示Couldnotfindadeclarationfileformodule'react',那么你应该执行如下命令:yarnadd@types/react这只限于第三方包,如果是项目自己的模块提示缺少声明文件,需要自己写相应的声明文件。比如你在全局对象窗口挂载了一个对象,如果需要使用它,就需要声明一下,否则会报错。至于怎么写,就看typescript文档了,这里就不多说了。https://www.tslang.cn/docs/ha...Cannotfindtypedefinitionfilefor'**'这些不是我们业务代码中直接使用的,而是第三方包使用的。此时需要检查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'**'hasnodefaultexport提示模块代码中没有"exportdefault",但是你使用了"importfrom"的默认导入形式。针对这个问题,我们需要将tsconfig.json的配置项“allowSyntheticDefaultImports”设置为true。允许从没有默认导出集的模块中进行默认导入。不过不用担心对代码的影响,这只是为了类型检查。{"compilerOptions":{"allowSyntheticDefaultImports":true}}当然你也可以使用配置项"esModuleInterop",设置为true。根据“allowSyntheticDefaultImports”的默认值,如下:module==="system"or--esModuleInterop对"esModuleInterop"配置项有两个主要作用:提供__importStar和__importDefault两个helper来兼容babelecology和enableallowSyntheticDefaultImports对于“esModuleInterop”和“allowSyntheticDefaultImports”的选择,如果typescript需要结合babel,没有问题就选择“esModuleInterop”,否则我习惯选择“allowSyntheticDefaultImports”,我更喜欢使用我需要的东西。当然,“esModuleInterop”是最安全的选择。如果你不确定这一点,那就乖乖用“esModuleInterop”吧。无法识别文档和窗口等全局对象。这种情况下,我们需要在tsconfig.json中的lib配置项中添加一个dom库,如下:{"compilerOptions":{"lib":["dom",...,"esNext"]}}的文件中的红色标记关于这个问题,我们需要考虑两种情况,第一种是.ts文件,第二种是.tsx文件。下面我们来看看具体需要注意的点(ps:下面说的几点不能完全解决文件中标红的问题,但是可以解决大部分标红的问题):***Type:.ts文件你项目中的文件比较少,比较好处理。根据实际情况添加类型限制,没有什么特别要说的。第二种:.tsx文件在本例中都是react组件,react组件分为stateless组件和stateful组件,下面分别来看。无状态组件对于无状态组件,首先要限制它是一个FunctionComponent(函数组件),其次要限制它的props类型。例如🌰:importReact,{FunctionComponent,ReactElement}from'react';import{LoadingComponentProps}from'react-loadable';import'./style.scss';interfaceLoadingPropsextendsLoadingComponentProps{loading:boolean,children?:ReactElement}constLoading:FunctionComponent