Thursday, July 28, 2022
HomeWeb DevelopmentThe right way to incrementally migrate a Gatsby app to TypeScript

The right way to incrementally migrate a Gatsby app to TypeScript


It shouldn’t come as a shock that TypeScript is getting extra traction amongst builders by the day. Help for it has grown significantly, in addition to the group and variety of tasks adopting this expertise.

It wasn’t all the time like that, although. Internet builders have been burned earlier than by sizzling applied sciences that disappeared, and it’s solely truthful that some in the neighborhood are extra skeptical about large adjustments. In reality, the Lindy impact proposes that daily a bit of expertise continues to outlive, the longer it’s anticipated to exist.

The purpose of this text is to not persuade you emigrate to TypeScript; I assume that if you’re right here, you might have already been offered on the advantages of static typing in a dynamic language like JavaScript. Nonetheless, if you’re like me, you most likely have been delaying the migration, frightened of the quantity of labor wanted to set it in movement.

Nicely, worry no extra! I’ve accomplished the heavy lifting for you. On this article, you’ll learn to undertake TypeScript incrementally, so you’ll be able to have a clean transition and a very good evening of sleep after work.

Contents

Why incrementally?

Why do now we have “incrementally” within the title of this text? Isn’t that simply delaying the inevitable? Why not carry out a full migration directly?

These are legitimate factors, and in some circumstances, they will even be essentially the most advisable. Nonetheless, I’m assuming you might have a considerably giant venture, large enough that utilizing a codemod gained’t work (or would require an excessive amount of workaround).

Or possibly you’re employed on a particular a part of an app in a bigger staff and wish to run a pilot earlier than doing the massive change.

In all circumstances, there are legitimate eventualities the place one would take the cautionary street first. And regardless that you will see that a bunch of codemods or migration strategies that declare to be seamless, the truth is that in case your venture has some complexity, it may not be as straightforward as they preach.


Extra nice articles from LogRocket:


Nonetheless, to supply a counterpoint, the oldsters at Stripe appear to disagree with me. They simply not too long ago printed a piece claiming to have migrated thousands and thousands of traces of code to TypeScript. If you’re feeling adventurous, it’s price checking it out!

The right way to arrange TypeScript in an present Gatsby app

Alright, for immediately’s experiment we’ll assume you have already got a Gatsby app and wish to carry out a gradual migration.

Keep in mind that if you’re creating a brand new venture immediately, Gatsby already helps TypeScript as the primary language from the start. Sadly, that’s not the case for many tasks that have been bootstrapped in older variations of Gatsby, so we’re going to take a distinct route.

The Gatsby docs already current a good information on the right way to migrate. Nonetheless, there are a couple of tweaks that we have to do so as to get it up and operating easily.

Change your .js recordsdata to .tsx

The better half is to vary all parts you wish to migrate to .tsx, or create new ones on this format. No work is required on Gatsby’s aspect for this to work! That’s fairly neat.

Set up dependencies

There are, nevertheless, some libraries to be put in. Be sure to add them to your devDependencies:

$ npm i –save-dev @varieties/node @varieties/react @varieties/react-dom typescript 

Generate .tsconfig

TypeScript has a config file known as .tsconfig, which is vastly customizable and can fluctuate from venture to venture. Nonetheless, there are some particular adjustments we have to make so as to enable TypeScript and JavaScript to coexist in concord, as this can be a requirement for everybody to undertake TS steadily.

An instance of a working .tsconfig is as follows. Be certain so as to add it to the basis folder of your venture:

{
  "compilerOptions": {
    "goal": "es2016",
    "jsx": "react",
    "module": "commonjs",
    "allowJs": true,
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "exclude": ["node_modules", "public", ".cache"]
}

You can too test an instance on this public repo in GitHub.

Among the wanted configs are as follows:

  • Add "jsx": "react" to ensure the compiler is aware of we’re in a React venture
  • Set allowJs: true; as soon as JavaScript and TypeScript must coexist, this flag must be turned on
  • Add outDir: "./dist", which makes VS Code completely satisfied and prevents undesirable errors

Declaring globals

Should you received this far, you have already got most of your setup working. Nonetheless, there are nonetheless some tough edges.

The obvious is about CSS modules; Gatsby works with CSS modules by default and we have to let TypeScript be completely satisfied about it. Should you use SVGs as parts as described right here, this will even be helpful.

On the src folder of your venture, create a file known as globals.d.ts and add the next:

declare module "*.module.css";
declare module "*.module.scss";
declare module "*.svg" {
  const content material: string;
  export default content material;
}

This can ensure that each CSS and SVG are handled and dealt with as modules.

Once more, you’ll be able to test a working instance in GitHub.

If you’re utilizing ESLint, it could complain about .d.ts recordsdata. On this case, you’ll be able to disable the linter in such extensions.

Typing utilizing prop varieties

One of many most important benefits of TypeScript is to permit static typing in JavaScript. When growing with React, that is a lot welcomed, as a result of it makes it more durable for us so as to add non-existing props and even move the incorrect variable.

Earlier than TypeScript was a factor, the React staff popularized typechecking with prop varieties.

Prop varieties have been an middleman step between no validation and strict typing. With prop varieties, builders might listing all props in a given element, their corresponding sort, and whether or not they’re optionally available or necessary.

For instance, suppose now we have a element that receives a prop known as magicNumber, which in fact ought to have the sort quantity:

import PropTypes from 'prop-types'

const MyComponent = ({ magicNumber }) => { … } 

MyComponent.propTypes = {
  magicNumber: PropTypes.quantity.isRequired
} 

Suppose then that we render MyComponent however overlook to move magicNumber as prop, or move a string as an alternative. We’d see a warning like this within the console, when in dev mode:

warning in dev mode

Nonetheless, there could be no static validation, and it’s straightforward to miss this type of error in larger parts or bigger tasks. Additionally, we are able to add a prop however overlook to set its sort (there are some linters that provide help to with that although).

Utilizing static typing, you’ll be able to deprecate prop varieties in favor of normal TypeScript varieties:

sort Props = {
  magicNumber: quantity
}

const MyComponent = ({ magicNumber }: Props) => { … } 

Now, you probably have a .tsx element that renders MyComponent, passing a prop with the incorrect sort will elevate an error at construct time:

build time error

And that’s it! Safer, however much less verbose, and comes with all typing advantages. All in all, prop varieties work however are much less highly effective than a strong typing technique like TypeScript. If you wish to get deeper on this topic, I like to recommend you learn our preview article on the topic: Evaluating TypeScript and PropTypes in React purposes.

If you’re satisfied that static typing is superior to prop varieties, you must also know that there’s a caveat when ditching prop varieties in a venture that may be a hybrid of TypeScript and JavaScript.

Suppose that now we have a WithTypeScript.tsx element that renders the TypeScript model of MyComponent. If we attempt to move magicNumber="Hi there World" that is going to boost an error as soon as there’s a sort mismatch, as seen above.

Nonetheless, if WithTypeScript.tsx receives magicNumber from a mother or father element written in pure JavaScript and passes it alongside to MyComponent.tsx, there is no such thing as a solution to validate if the variable is certainly a quantity. As soon as the mother or father element has no typing, no static error might be raised. And since there are not any prop varieties in MyComponent.tsx, no runtime error might be raised. As such, this kind mismatch gained’t be raised anyplace.

no runtime error

Word how IndexPage.js calls a TypeScript element WithTypeScript.tsx with a incorrect prop sort. No warning is seen both within the editor or within the browser console.

Keep in mind that this solely occurs when .js and .tsx parts are speaking, which is able to inevitably occur if you’re steadily adopting TypeScript. Thankfully, there’s an answer for it: we are able to have one of the best of each worlds by inferring varieties from prop varieties in TypeScript parts. This manner, we retain the prop varieties, however routinely convert them into varieties utilizing the operate InferProps from the prop-types library.

This could be MyComponent.tsx combining varieties and prop varieties:

import React from "react";
import PropTypes, { InferProps } from "prop-types";

const Props = {
  magicNumber: PropTypes.quantity.isRequired,
};

sort MyComponentTypes = InferProps<typeof Props>;

const MyComponent = ({ magicNumber }: MyComponentTypes) => { … };

MyComponent.propTypes = Props;

export default MyComponent;

A full instance could be seen right here.

The above answer will elevate a static error at construct time if there’s a sort mismatch, but in addition elevate a runtime error within the browser console if the incorrect sort is handed from a .js to a .ts element alongside the way in which. The disadvantage is that your code turns into extra verbose.

Nonetheless, if newer parts solely talk with different .ts recordsdata, then it must be secure to ditch prop varieties. Ultimately, when the migration is full, you’ll be able to fully take away them.

Conclusion

TypeScript is an distinctive tooling, however some builders chorus from adopting it in an present codebase. This text aimed to elucidate how you are able to do it safely in your venture, proper now, with out main adjustments.

Whereas Gatsby specifically helps .tsx recordsdata out of the field, you want some workarounds to make your compiler completely satisfied contemplating typical approaches current in Gatsby codebases. Declaring globals for CSS Modules and SVGs are widespread ache factors.

Lastly, by having JavaScript speaking with TypeScript, we are able to’t assure that some typing errors gained’t be opaque. Due to that, we are able to leverage the prop-types library and infer the kinds, getting one of the best of each worlds till we’re secure to deprecate.

All code and examples current on this article could be present in this repo in GitHub. Give it a strive!

Writing numerous TypeScript? Watch the recording of our latest TypeScript meetup to study writing extra readable code.

TypeScript brings sort security to JavaScript. There generally is a rigidity between sort security and readable code. Watch the recording for a deep dive on some new options of TypeScript 4.4.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments