By default the code behind a Gatsby site is written in JavaScript. However, as a site scales it can become more difficult to maintain all of that JavaScript. One way to improve the scalability of the site is to migrate from JavaScript to TyepScript.
🚀 TL;DR
Show me the code. Look at the 1-typescript
branch.
What is TypeScript?
TypeScript is a superset of JavaScript (all JavaScript code is valid TypeScript code). JavaScript is dynamically typed, which means that the type of a variable is determined at runtime. In contrast, TypeScript is statically typed, with the type of variables being determined at compile-time. This help developers rigorously define the type and form of their objects, so that type-related errors can be caught earlier in the development cycle.
Porting from JavaScript to TypeScript
The change from JavaScript to TypeScript should be done incrementally. Make small changes and ensure that nothing breaks with each change.
We’ll use the Gatsby Starter Project discussed in a previous post as the starting point. Clone that repository.
File Types
When you start working with TypeScript you’ll notice that there are two common file extensions: .ts
and .tsx
. What’s the difference?
.ts
files contain pure TypeScript and.tsx
files can also include JSX content (analogous to.jsx
files for JavaScript).
💡 JSX (JavaScript XML) is an extension to JavaScript, primarily used with React. It allows developers to write HTML elements and components using a JavaScript-like syntax.
We’re going to simply rename our JavaScript files, implicitly turning them into TypeScript files.
- Go into the
src/pages
folder and change the extensions on all of the files from.js
to.tsx
. - Go into the
src/components
folder. Change the extensions onheader.js
,layout.js
andseo.js
to.tsx
.
Rebuild the site and take a look. The site should not have changed.
Add Dependencies
Make the following edits to package.json
:
- in the
dependencies
section addgatsby-plugin-typescript
; and - in the
devDependencies
section add@typescript-eslint/eslint-plugin
,@typescript-eslint/parser
andtypescript
.
Rebuild the site so that those packages get installed.
Create a Configuration File
We can use the TypeScript Compiler, tsc
, to generate a default configuration file.
First spin up a Node environment.
docker run -it -v ${PWD}:/site --entrypoint /bin/bash datawookie/gatsby:latest
Now create a fresh tsconfig.json
file.
# Using Node Package eXecute.
npx tsc --init
# Using Yarn.
yarn tsc --init
Most of the file will be commented out. What remains should look something like this:
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Uncomment the entry for jsx
and set the value to "react"
.
{
"compilerOptions": {
"target": "es2016",
"jsx": "react",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Implicit Any Type
Try to compile the TypeScript using either of the following commands.
npx tsc
yarn tsc
You will probably get a bunch of TS7031 errors, which arise because variables are implicitly being typed as any
. Fix these by assigning explicit types to those variables.
Type Declarations for CSS
Try to compile again. You will get a TS2307 error because TypeScript is looking for type definitions in a CSS file.
We could fix this manually. But it’s easier and more robust to use a package which is designed specifically to deal with it. Install the typed-css-modules
package (this is included in the "package.json"
file). The package comes with a utility, tcm
. Run it using either of the following commands.
npx tcm src -p
yarn tcm src -p
That will find all CSS files under the src
folder and create a declaration file (with a .d.ts
extension) for each of them.
At this stage all errors should have been resolved and your TypeScript will compile smoothly.
Automating TypeScript Checks
Gatsby won’t check your TypeScript files. But you can run tsc
over your code before running gatsby
by making a simple update to package.json
:
"scripts": {
"build": "tsc --noEmit && gatsby build",
"develop": "tsc --noEmit && gatsby develop",
"start": "tsc --noEmit && gatsby develop"
}
Now if you run yarn build
(or yarn develop
or yarn start
) your TypeScript code will be checked first. The --noEmit
flag tells tsc
not to produce any JavaScript code.
Conclusion
By enforcing a level of type safety and providing a richer development environment, TypeScript helps to ensure that large-scale projects remain clean, organised, and bug-free, which in turn, enhances productivity and long-term maintainability.
The code for this post can be found here.