cdcasey.dev

gatsbyhireactsite info

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 parser
3 extends: [
4 'airbnb',
5 'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react
6 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
7 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
8 '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 features
12 sourceType: 'module', // Allows for the use of imports
13 ecmaFeatures: {
14 jsx: true, // Allows for the parsing of JSX
15 },
16 },
17 rules: {
18 // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
19 // 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 use
24 },
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": true
24 },
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();
3
4 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};
4
5export function Layout({ children }: ExportProps): React.ReactElement {
6 const { title, description } = useSiteMetadata();
7
8 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!

next: Adding Posts

prev: Making Changes