示例倉庫 https://github.com/XYShaoKang...javascript
以前花了些時間將gatsby-theme-gitbook
遷移到 Typescript,以得到在 VSCode 中更好的編程體驗.總體差很少已經完成遷移,剩下將 Gatsby 的 API 文件也遷移到 TS,這裏能夠看到 gatsby#21995 官方也在將核心代碼庫遷移到 Typescript,準備等待官方將核心代碼庫遷移完成,在遷移 API 文件.html
這篇文章用XYShaoKang/gatsby-project-config,演示如何將 gatsby 遷移到 TypeScript,但願能幫到一樣想要在 Gatsby 中使用 TS 的同窗.java
遷移步驟:node
gatsby-plugin-codegen
完善 GraphQL 類型提示gatsby new gatsby-migrate-to-typescript XYShaoKang/gatsby-project-config cd gatsby-migrate-to-typescript yarn develop
typescript
typescript.json
配置文件typescript
yarn add -D typescript
tsconfig.json
// https://www.typescriptlang.org/v2/docs/handbook/tsconfig-json.html { "compilerOptions": { "target": "esnext", // 編譯生成的目標 es 版本,能夠根據須要設置 "module": "commonjs", // 編譯生成的目標模塊系統 "lib": ["dom", "es2015", "es2017"], // 配置須要包含的運行環境的類型定義 "jsx": "react", // 配置 .tsx 文件的輸出模式 "strict": true, // 開啓嚴格模式 "esModuleInterop": true, // 兼容 CommonJS 和 ES Module "noUnusedLocals": true, // 報告未使用的局部變量的錯誤 "noUnusedParameters": true, // 報告有關函數中未使用參數的錯誤 "experimentalDecorators": true, // 啓用裝飾器 "emitDecoratorMetadata": true, // 支持裝飾器上生成元數據,用來進行反射之類的操做 "noEmit": true, // 不輸出 js,源映射或聲明之類的文件,單純用來檢查錯誤 "skipLibCheck": true // 跳過聲明文件的類型檢查,只會檢查已引用的部分 }, "exclude": ["./node_modules", "./public", "./.cache"], // 解析時,應該跳過的路晉 "include": ["src"] // 定義包含的路徑,定義在其中的聲明文件都會被解析進 vscode 的智能提示 }
將index.js
改爲index.tsx
,從新啓動服務,查看效果.react
其實 Gatsby 內置了 支持 TS,不用其餘配置,只要把index.js
改爲index.tsx
就能夠直接運行.添加 TS 依賴是爲了顯示管理 TS,而tsconfig.json
也是這個目的,當咱們有須要新的特性以及自定義配置時,能夠手動添加.
打開index.tsx
,VSCode 會報兩個錯誤,一個是找不到styled-components
的聲明文件,這個能夠經過安裝@types/styled-components
來解決.
另一個錯誤綁定元素「data」隱式具備「any」類型。
,這個錯誤是由於咱們在tsconfig.json
中指定了"strict": true
,這會開啓嚴格的類型檢查,能夠經過關閉這個選項來解決,只是咱們用 TS 就是要用它的類型檢查的,因此正確的作法是給data
定義類型.
下面來一一修復錯誤.git
安裝styled-components
的聲明文件github
yarn add -D @types/styled-components
修改index.tsx
web
import React, { FC } from 'react' // ... interface PageQuery { data: { allMarkdownRemark: { edges: Array<{ node: { frontmatter: { title: string } excerpt: string } }> } } } const Home: FC<PageQuery> = ({ data }) => { const node = data.allMarkdownRemark.edges[0].node const title = node.frontmatter?.title const excerpt = node.excerpt return ( <> <Title>{title}</Title> <Content>{excerpt}</Content> </> ) } export default Home // ...
這時候會出現一個新的錯誤,在excerpt: string
處提示Parsing error: Unexpected token
,這是由於 ESLint 還沒法識別 TS 的語法,下面來配置 ESLint 支持 TS.typescript
安裝依賴編程
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
配置.eslintrc.js
module.exports = { parser: `@typescript-eslint/parser`, // 將解析器從`babel-eslint`替換成`@typescript-eslint/parser`,用以解析 TS 代碼 extends: [ `google`, `eslint:recommended`, `plugin:@typescript-eslint/recommended`, // 使用 @typescript-eslint/eslint-plugin 推薦配置 `plugin:react/recommended`, `prettier/@typescript-eslint`, // 禁用 @typescript-eslint/eslint-plugin 中與 prettier 衝突的規則 `plugin:prettier/recommended`, ], plugins: [ `@typescript-eslint`, // 處理 TS 語法規則 `react`, `filenames`, ], // ... }
在.vscode/settings.json
中添加配置,讓VSCode
使用ESLint
擴展格式化ts
和tsx
文件
// .vscode/settings.json { "eslint.format.enable": true, "[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[javascriptreact]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescriptreact]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" } }
// index.tsx import React, { FC } from 'react' // ... interface PageQuery { data: { allMarkdownRemark: { edges: Array<{ node: { frontmatter: { title: string } excerpt: string } }> } } } const Home: FC<PageQuery> = ({ data }) => { // ... } export default Home export const query = graphql` query { allMarkdownRemark { edges { node { frontmatter { title } excerpt } } } } `
咱們看看index.tsx
文件,會發現PropTypes
和query
結構很是相似,在Gatsby
運行時,會把query
查詢的結果做爲組件prop.data
傳入組件,而PropTypes
是用來約束prop
存在的.因此其實PropTypes
就是根據query
寫出來的.
若是有依據query
自動生成PropTypes
的功能就太棒了.
另一個問題是在query
中編寫GraphQL
查詢時,並無類型約束,也沒有智能提示.
這兩個問題能夠經過gatsby-plugin-codegen
擴展來解決.gatsby-plugin-codegen
會生成apollo.config.js
和schema.json
,配合vscode-apollo
擴展,能夠提供GraphQL
的類型約束和智能提示.
另外會自動根據query
中的GraphQL
查詢,生成 TS 類型,放在對應的tsx
文件同級目錄下的__generated__
文件夾,使用時只須要引入便可.
這裏要注意,Apollo
不支持匿名查詢,須要使用命名查詢另外須要運行
Gatsby
以後才能經過gatsby-plugin-codegen
生成類型文件
下面是具體操做
vscode-apollo
擴展在 VSCode 中按 Ctrl + P
( MAC 下: Cmd + P
) 輸入如下命令,按回車安裝
ext install apollographql.vscode-apollo
gatsby-plugin-codegen
依賴在項目中添加依賴
yarn add gatsby-plugin-codegen
gatsby-config.js
添加gatsby-plugin-codegen
插件
// gatsby-config.js module.exports = { plugins: [ // ... { resolve: `gatsby-plugin-codegen`, options: {}, }, ], }
Gatsby
生成類型文件yarn develop
若是出現如下錯誤,通常是由於沒有爲查詢命名的緣故,給查詢添加命名便可,另外配置正確的話,打開對應的文件,有匿名查詢,編輯器會有錯誤提示.
這個命名以後會做爲生成的類型名.
index.tsx
以使用生成的類型gatsby-plugin-codegen
插件會更具查詢生成對應的查詢名稱的類型,保存在對應tsx
文件同級的__generated__
目錄下.使用時引入便可.
import { HomeQuery } from './__generated__/HomeQuery' // 引入自動生成的類型 // ... // interface PageQuery { // data: { // allMarkdownRemark: { // edges: Array<{ // node: { // frontmatter: { // title: string // } // excerpt: string // } // }> // } // } // } interface PageQuery { data: HomeQuery // 替換以前手寫的類型 } // ...
.gitignore
中apollo.config.js
,schema.json
,__generated__
能經過運行時生成,因此能夠添加到.gitignore
中,不用提交到 git 中.固然若是有須要也能夠選擇提交到 git 中.
# Generated types by gatsby-plugin-codegen __generated__ apollo.config.js schema.json