示例仓库 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