TypeScript 項目實戰
在 React 項目中使用 TypeScript
1. 在項目里安裝 TypeScript 編譯器,並在工程根目錄運行 tsc --init,自動產生tsconfig.json文件。初始化得到的 tsconfig.json,增加"allowJs": true,"jsx": "react" 選項,antd 3 以前的版本需要在 tsconfig.json 的 compilerOptions 中配置 "allowSyntheticDefaultImports": true。詳細配置參考TypeScript 官方文檔。tips: npm 安裝不成功或者超級慢時建議使用鏡像
npm install --save-dev typescripttsc --init
2. 增加react聲明文件,react 和 react 的聲明文件的版本需一致
npm install --save-dev @types/react @types/react-dom @types/react-redux
3. 增加 ts 的loader,可參考Webpack & Typescript,如 awesome-typescript-loader。同時添加 resolve.extensions
來告訴 webpack 在解析查找 TypeScript 模塊時該檢索哪些文件擴展名。
npm install --save-dev awesome-typescript-loader
webpack 配置
module: { rules: [ { test: /.(ts|tsx)$/, exclude: /node_modules/, loader: "awesome-typescript-loader", } ] }, resolve: { extensions: [".tsx", ".ts", ".js",".jsx"] }
4. 新項目可以參考 TypeScript-React-Starter
error fix
1. 找不到引入的 less 文件
寫聲明文件或者安裝插件 typings-for-css-modules-loader
npm install --save-dev typings-for-css-modules-loader
webpack 配置,將css-loader 換成 typings-for-css-modules-loader ,保持原來的配置不變, loader 將會生成聲明 less 的文件,使用 Webpack 的 WatchIgnorePlugin 插件配置來忽略它們
module: { rules: [ { test: /.less$/, use: [ "style-loader", { loader: typings-for-css-modules-loader, options: { modules: true, namedExport: true, camelCase:true, } }, // { // loader: "css-loader", // query: { // importLoader: 1, // localIdentName: "[path]___[name]__[local]___[hash:base64:5]", // modules: true // } // }, "postcss-loader", "less-loader" ] }, ]},plugins: [ new webpack.WatchIgnorePlugin([ /css.d.ts$/ ]), ... ]
bug:TS2307: Cannot find module ./styles.less. 遇到這種情況時重啟項目
2. ERROR in [at-loader] ./node_modules/_antd@2.13.11@antd/lib/table/Table.d.ts:117:27
TS2304: Cannot find name PropertyKey
解決方案:tsconfig.json 中配置 "lib": ["es6", "dom"], "moduleResolution": "node",
3. antd 2.8.1版本報錯 : TS2416: Property componentWillReceiveProps in type Mention is not assign...
解決方案:2.13.11版本和3.2.3版本都沒有這個錯。。。最後只能升到3.2.3版本
4. error TS2605: JSX element type Xxx is not a constructor function for JSX elements
解決方案:compilerOptions
中配置 "allowSyntheticDefaultImports": true
antd 3 以前的版本 Row 、Col 等組件會出現這個錯誤
5. 版本問題,版本之間的差異會導致很多問題
需要卸載模塊的可以用這條命令
rm -rf node_modules && npm cache clean && npm uninstall
部分package.json 配置
react-router 用的是3.0.2 版本,安裝 @types/react-route 後,找不到 history 下面的方法,還需要安裝一個 history 模塊
「dependencies」:{ "react": "^15.5.0", "react-dom": "^16.0.3", "react-redux": "^5.0.4", "react-router": "3.0.2" , "history": "^3.3.0", }"devDependencies": { "awesome-typescript-loader": "^3.5.0", "@types/node": "^8.0.50", "@types/react": "^15.6.6", "@types/react-dom": "^0.14.22", "@types/react-redux": "^4.4.36", "@types/react-router": "3.0.2" }
6. 項目啟動之後的 error : react-hot-loader.development.js:95 React-hot-loader
- 查看一下 package.json 文件中 react-hot-loader 的版本是 next,我執行了 npm install ,react-hot-loader 也會安裝,版本就不對應了,建議改成固定版本號如 ^4.0.0
- 關於 React Hot Loader 插件,使用 typescript 時 Babel 不是必須的,但是 React Hot Loader 需要它,在 Webpack 中添加 babel-loader ,此處參考 react-hot-loader
{ test: /.(ts|tsx)$/, exclude: /node_modules/, use: [ { loader: babel-loader, options: { presets: [ "es2015-ie", "stage-0", "react" ], plugins: [react-hot-loader/babel], }, }, awesome-typescript-loader, ],}
同時需要修改 tsconfig.json的配置
{ "module": "commonjs", "target": "es6"}
7. 找不到使用絕對路徑的模塊
解決方案: 在 tsconfig.json 裡面設置路徑解析,如 {"baseUrl": "./app", },baseUrl的值不會對相對文件的引入產生影響,moduleResolution
標記(node, classic)指定使用哪種模塊解析策略,參考模塊解析
8. antd Form 組件的用法
import { Form } from antd;import { FormComponentProps } from antd/lib/form;interface UserFormProps extends FormComponentProps { age: number; name: string;}class UserForm extends React.Component<UserFormProps, any> {}
9. TS2339: Property xxx does not exist on type IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick<any, never>, ComponentState>> & Rea....
解決方案:在組件中聲明 props
constructor(props:QueryProps){ super(props) }
10. TS2339: Property xxx does not exist on type any[]....
解決方案:
- 在代碼中有給函數參數賦值{} ,ts會推導node類型就是{},裡面無屬性
createJobDir = (node={}) => { ...node.id...// } //改成interface Node { id:string;}createJobDir = (node:Node) => { ...node.id...// }
- 函數返回值的推斷,ts 根據返回值推斷出 {} 類型找不到 expandedKeys 屬性報錯
const searchRet = getSearchTreeData(param1,param2) this.setState({ expandedKeys: searchRet.expandedKeys })//改成 const searchRet:any = getSearchTreeData(param1,param2)
附上 tsconfig.json 的配置
{ "compilerOptions":{ "target": "es6", /* Specify ECMAScript target version: ES3 (default), ES5, ES2015, ES2016, ES2017, or ESNEXT. */ "module": "commonjs", /* Specify module code generation: none, commonjs, amd, system, umd, es2015, or ESNext. */ "lib": ["es6", "dom"], /* Specify library files to be included in the compilation: */ "allowJs": true, /* Allow javascript files to be compiled. */ "jsx": "react", /* Specify JSX code generation: preserve, react-native, or react. */ "sourceMap": true, /* Generates corresponding .map file. */ "outDir": "./dist/", /* Redirect output structure to the directory. */ "moduleResolution": "node", /* Specify module resolution strategy: node (Node.js) or classic (TypeScript pre-1.6). */ "baseUrl": "./app", /* Base directory to resolve non-absolute module names. */ "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */ } "exclude": [ "node_modules", "build", "scripts", "pkgcmd", "server", "docs", "internals", "vendors" ]}
未完待更。。。
推薦閱讀:
※推斷函數返回值的類型
※angular 和 typescript 到底是否適合最佳實踐?
※VS Code 1.14更新日誌
※如何進一步熟悉甚至掌握Angular?
※手把手教寫 TypeScript Transformer Plugin
TAG:TypeScript | React |