Adding TypeScript
I am a complete TypeScript n00b, but I love everything about it that I have used so far. This section is fraught with peril, but I'm confident things will turn out ok in the end. It does occur to me at this point that I could have just used this starter and swapped out Emotion for Styled Component. But miss out on all the learning that comes from building it myself? No thank you.
Adding TypeScript Itself
The first step is to run the following commands:
1yarn add typescript gatsby-plugin-typescript
1npx install-peerdeps --dev eslint-config-airbnb
Today I found out that this works with Yarn (from a prompt)! I would like to take this moment to say that the very idea of peer dependencies just seems dumb.
1yarn add -D @types/react @types/react-dom @types/node eslint eslint-config-prettier eslint-plugin-prettier
Now it's time to add `gatsby-plugin-typescript`
to the plugins section of gatsby-config.js
.
Finally, it's time for some configs. I have eslint configurations for a small TypeScript project that I did, and I have one for a Gatsby project that I did. However, they use different parsers, so I'm not sure what the right thing do do it here. For now, I copy the one from the TypeScript project and see how it goes.
.eslintrc.js
1module.exports = {2 parser: '@typescript-eslint/parser', // Specifies the ESLint parser3 extends: [4 'airbnb',5 'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react6 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin7 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier8 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.9 ],10 parserOptions: {11 ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features12 sourceType: 'module', // Allows for the use of imports13 ecmaFeatures: {14 jsx: true, // Allows for the parsing of JSX15 },16 },17 rules: {18 // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs19 // e.g. "@typescript-eslint/explicit-function-return-type": "off",20 },21 settings: {22 react: {23 version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use24 },25 },26};
I like to be able to lint from the command line, so I add the following to the scrips section of my package.json
:
1"lint": "eslint -c .eslintrc.js --ext .js --ext .jsx --ext .ts --ext .tsx --ignore-path .gitignore .",
Running the linter manually returns an error saying that I forgot the @typescript-eslint/eslint-plugin
.
1yarn add -D @typescript-eslint/eslint-plugin
Yet another error reveals I need to install the parser manually as well. JavaScript, am I right?
1yarn add -D @typescript-eslint/parser
Now linting works! As I have Prettier installed, I'm deciding to not rely on VS Code's settings and create my own .prettierrc.js.
1module.exports = {2 semi: true,3 trailingComma: 'all',4 singleQuote: true,5 printWidth: 100,6 tabWidth: 2,7 arrowParens: 'always',8};
Since I have a Prettier configuration for the project, I'd like to be able to run it manually as well. The following go into the scripts section of the package.json
file:
1"prettier": "prettier --ignore-path .gitignore \"**/*.+(js|jsx|ts|tsx|json|css|scss)\"",2 "format": "yarn prettier -- --write",
Now for the .tsconfig.json
file. As I'm a TypeScript n00b, I just copy and paste the file I have in my existing TS project.
1{2 "compilerOptions": {3 "baseUrl": "src",4 "target": "es5",5 "lib": ["dom", "dom.iterable", "esnext"],6 "allowJs": true,7 "skipLibCheck": true,8 "esModuleInterop": true,9 "allowSyntheticDefaultImports": true,10 "strict": true,11 "forceConsistentCasingInFileNames": true,12 "module": "esnext",13 "moduleResolution": "node",14 "resolveJsonModule": true,15 "noEmit": true,16 "jsx": "react",17 "sourceMap": true,18 "declaration": true,19 "noUnusedLocals": true,20 "noUnusedParameters": true,21 "experimentalDecorators": true,22 "noFallthroughCasesInSwitch": true,23 "isolatedModules": true24 },25 "include": ["src/**/*"],26 "exclude": ["node_modules", "build"]27}
Running yarn develop
reveals that everything is still working. Now I can change things like this
1export function Layout({ children }) {2 const { title, description } = useSiteMetadata();34 return (5 <AppStyles>6 <Header siteTitle={title} siteDescription={description} />7 {children}8 </AppStyles>9 );10}
to this
1type ExportProps = {2 children: React.ReactChild | React.ReactChildren,3};45export function Layout({ children }: ExportProps): React.ReactElement {6 const { title, description } = useSiteMetadata();78 return (9 <AppStyles>10 <Header siteTitle={title} siteDescription={description} />11 {children}12 </AppStyles>13 );14}
Time for a commit, and back to the tutorial tomorrow!