Adding Typescript Part 1

react logo typescript logo


Why Add Typescript

Over the past few years Typescript has gained popularity & almost every new frontend project is based on it.

Changing the site to it makes sense for future development & maintainability.

There are also a lot of advantages over React prop-types.

React prop-types only provides component based type checking.
With typescript we gain type checking over the project at compile time.

Adding Typescript

Install Dependencies

pnpm i typescript
pnpm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser

Add a Typescript Config

tsconfig.json

{
    "compilerOptions": {
        "module": "CommonJS",
        "target": "ESNext",
        "lib": [
            "DOM",
            "ESNext"
        ],
        "strict": true,
        "moduleResolution": "node",
        "sourceMap": true,
        "jsx": "preserve",
        "allowJs": true,
        "noEmit": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "noImplicitAny": false,
        "forceConsistentCasingInFileNames": true,
        "allowSyntheticDefaultImports": true,
    },
    "exclude": [
        "node_modules",
        "public",
        ".cache"
    ]
}
You may want to start with strict: false then work towards enabling strict mode later.

ESLint & Typescript

Update ESLint config to use Typescript.

  • set parser to @typescript-eslint/parser
  • enable @typescript-eslint plugin
  • add plugin:@typescript-eslint/recommended to extends
  • enable .tsx file extension in react/jsx-filename-extension
  • add .ts, .tsx to import/resolver

updated eslint config with typescript presets

Rename Files

  • find all js & jsx files in src/ with jsx content & rename them to .tsx
  • find all other js files in src/ & rename them to .ts

This can be achieved using bash to rename all js & jsx files in src/ which import react to .tsx & rename all others to .ts.


rename_tsx.sh

#!/bin/bash
rename_tsx() {
  fname="${1##*.}"
  content=$(cat $1)
  if [[ $content == *"import React"* ]]
  then
    mv "$1" "${1%.$fname}.tsx"
    echo "✔ moved jsx file $1 to ${1%.$fname}.tsx"
  else
    mv "$1" "${1%.$fname}.ts"
    echo "✔ moved $1 to ${1%.$fname}.ts"
  fi
}
echo "moving files with JSX content to TSX & others to TS ..."
echo
for file in $(find src -name "*.js" -o -name "*.jsx"); do
  rename_tsx $file
done
echo
echo "all files moved"

From React prop-types to Typescript

Fortunately I created this site using React prop-types for type checking.
This should make converting the site a bit quicker.

Conversion

  • remove prop-types import
  • move & reformat entries from propTypes to a new interface entry
  • reference new interface entry for types
--- a/src/cms/preview-templates/post-preview.js
+++ b/src/cms/preview-templates/post-preview.tsx
@@ -1,8 +1,12 @@
 import React from 'react'
-import PropTypes from 'prop-types'
 import PreviewTemplate from '../../templates/preview-template'

-const PostPreview = ({ entry, widgetFor }) => {
+interface PostPreviewProps {
+  entry: any
+  widgetFor: any
+}
+
+const PostPreview = ({ entry, widgetFor }: PostPreviewProps) => {
   const body = widgetFor('body')
   const title = entry.getIn(['data', 'title'])
   const date = entry.getIn(['data', 'date'])
@@ -11,9 +15,4 @@ const PostPreview = ({ entry, widgetFor }) => {
   return <PreviewTemplate body={body} title={title} date={date} image={image} />
 }

-PostPreview.propTypes = {
-  entry: PropTypes.object.isRequired,
-  widgetFor: PropTypes.object.isRequired,
-}
-
 export default PostPreview
It is possible to automate this process using a tool like jscodeshift.

Source Code

You can find the full pull request for the above changes of this site on github.

Add Typescript to Components

The source for the site is available on github.

equk-gatsby