I'm Learning TypeScript!

I'm Learning TypeScript!

Here's what I learned so far using it in Gatsby

ยท

5 min read

I finally gave in! After seeing a (sometimes annoying) barrage of tweets and posts urging developers to switch to TypeScript, I decided to just give it a shot. And you know what, I like it! I prefer the backend more, so I freeze up when I need to learn frontend stuff. But since last year I realized that I do love working with JavaScript frameworks like Gatsby, so learning TypeScript always felt inevitable. So, below I've written some stuff I've learned so far. This is not a tutorial, but there are some things below that could help you.

Preliminaries:

  • The first thing that I did was install TypeScript globally by running npm install -g typescript.
  • After that, I installed my Gatsby project and set it up.
  • Now I needed to get TypeScript working with Gatsby. The Gatsby CLI is able to automatically set up TypeScript, but I stupidly declined, so I had to set it up manually.
    • I installed the gatsby-plugin-typescript library for Gatsby.
    • After that I installed the typings for React by running npm install --save @types/react @types/react-dom.
    • Finally, I made the important tsconfig.json file. With compilerOptions I can override certain configurations for TypeScript's compiler. For example, I can compile my TypeScript down to an older version of ECMAScript with target.
{
    "compilerOptions": {
      "module": "commonjs",
      "target": "es5",
      "jsx": "react",
      "lib": ["dom", "es2015", "es2017"],
      "strict": true,
      "noEmit": true,
    },
  }

The Learning Begins: TypeScript offers all the features of JavaScript with the type system layered on top. This is why they call TypeScript a superset of JavaScript. TypeScript helps prevent weird things in JavaScript like below from happening.

EwYIDI2XMAEtz-B.png

  • The various basic types that we can assign to our variables and functions are boolean, number, and string. They have a special type called any too.
  • I learned that if an object has properties that are optional, we can use the ? operator after the property name so that TypeScript won't scream at us if we don't use it down the line.
  • We can also set our own types as well. There are a few ways to do this:
    • With Union Types, we can combine types to tell the compiler that the value can be two or more types. For example, we can denote that an ID can be of both number and string by typing id: number | string.
    • With Type Aliases, we can define a type and use it more than once. This is very useful, especially for objects. Check out the example below:
type Pet = {
    name: string
    species: string
    age: number
    shots: boolean
}

function checkPet(pet: Pet){
    ...
    console.log(pet.age) // will be a number
}
  • More:
    • Interfaces are pretty similar, but the main difference is that you can extend them by adding new properties. There are things that interfaces can do that Type Aliases can't such as being always named in error messages.
interface Pet {
    name: string
    species: string
    age: number
    shots: boolean
}
interface Dog extends Pet {
    breed: string
}

function checkPet(dog: Dog){
    ...
    console.log(dog.name) // will be a string
    console.log(dog.breed) // will be a string
}

The Learning Continues: For my project I am using Twin Macro, which is basically a way to implement TailwindCSS into React. I'm using it with Emotion, the well-known React package to implement styled-components (CSS in JS).

  • The first file that I worked on was seo.tsx. For each page, the best practice is to accept some props for SEO for each webpage, which almost always includes title. Some other props like description, lang, and author won't be used much, so I knew I had to make a type where I could make those props optional.
interface SEOProps {
    description?: string,
    lang?: string,
    title: string,
    author?: string
}

const SEO = ({description, lang, author, title}: SEOProps) => {
    ...
}
  • It can be tricky getting the syntax right at first. I placed my type outside of the parentheses instead of beside the object which caused the compiler to scream at me.
  • The next file I worked on was layout.tsx. In this file I simply just said that my child components can be of any type. I'm sure there's a proper way to do this in React or Gatsby. I probably will talk about it when I start doing deeper dives on this.
import React from 'react'

const Layout = ({children}: any) => (
    ...
)

The Learning Still Continues:

  • The way I usually set up my React projects is to have my components in folders with an index.js file and a styles.js file (the index.js file will take on the name of the component folder). I will then set up my styled-components in styles.js and import it into index.js. The process was familiar in TypeScript until I needed to include props.
  • In styles.tsx, I utilized the FunctionComponent type from React so that I could give a type to a component. Also, when I defined my type, I used an array as the property because I used the spread operator for my props. I'm struggling to describe this in words, so let me show you:
import React, {FC} from 'react'
import tw from 'twin.macro'

interface ComponentProps {
    [key: string]: any
}

const ThisButton: FC<ComponentProps> = props => <button {...props} />

export const Button = tw(ThisButton)`
    bg-blue-700 hover:bg-blue-900
`

Conclusion:

  • I'm having a lot of fun using TypeScript and I can see the reason for the hype. But I have a whole lot to learn.
  • In some future posts, I'll make some actual deep-dive tutorials about how to make a proper Gatsby website with styled-components, TailwindCSS, and of course, TypeScript.
ย