Why You Need to Use Typescript for All Your Web Projects

Why You Need to Use Typescript for All Your Web Projects
Example of a TypeScript component

I’ve been using TypeScript for two years, and I cannot imagine working on a new project that isn’t built on TypeScript. I love TypeScript so much that I wonder why it’s not the default on major frameworks.

What is TypeScript?

If we have to simplify by a lot, TypeScript is JavaScript but with types. This means that if you define a variable as a string, it will only accept strings. You won’t be able to set a number in that variable.

However, TypeScript goes far beyond typing variable. It will force you to test a potentially null variable, help you when writing code with autocomplete, or allow for more advanced features with generics. Let’s dive a bit deeper in that I just listed.

First, TypeScript will make you define your data structure. You won’t have to guess whether you have a firstname or firstName attributes on your users’ data. On top of that, you can tell TypeScript if a value is optional. As a result, TypeScript will force you to test the values before displaying them or performing operations on them.

export interface User {
  firstName: string
  lastName: string
  email: string 
  username?: string //This string is optional
  age?: number //This number is optional, either number or undefined
}
Example of an error thrown by TypeScript
export const getUserFullInformation = (user: User) => {
  const baseString = `${user.firstName} ${user.lastName.toUpperCase()}`

  if (user.username) {
    return `${user.username} - ${baseString}`
  }

  return baseString
}

Since TypeScript knows the type of data, it will suggest values as you type them. You might be used to this when using libraries, now your own code will be easier to write.

0:00
/

As I said before, TypeScript isn’t just describing your data. There are a lot of features that TypeScript proposes, one of them being generics. I won’t go into too much detail about generics in this article, but they allow writing type agnostic components or methods. The generic define the data the method expects.

This is particularly useful for lists or tables. It allows you to have one common implementation of the list while having multiple type of items that can be placed within it. React-table is a great example that uses generics for tables.

The following code show how we implemented a list of items in a project I recently worked on. We have a standard ListDisplay that can show items regardless of the type of data. Having this means, we can have a standardized way of handling lists and responsiveness.

The interface defines a TItem, this is the generic, and it’s used to know what type of data we have and what type of card to display.

interface Props<TItem> {
  title: string
  listItems: TItem[]
  card: (item: TItem, key: number) => ReactNode
}

function ListDisplay<T>({ title, listItems, card }: Props<T>) {
  return <div>{/*Place your UI here*/}</div>
}

const Temp = () => {
  const news: News[] = []

  return (
    <ListDisplay<News>
      title='More news'
      listItems={news}
      card={(item, key) => <NewsCard news={item} key={key} />}
    />
  )
}

Why TypeScript is good

Safety and Testing

The first advantage that comes to mind is the peace of mind that it provides to developers. No need to worry about making typos when getting attributes or having an undefined value.

Having to test values can be cumbersome at the time, but that will only make your app safer. Besides, this isn’t as taxing as some people make it look like. Doing some {event && <p>{event.title}</p>} to make sure that, you actually have data is clean and concise.

Collaborative Work and Project Understanding

TypeScript also tremendously help with the team work and project understanding. Knowing with confidence your data structure not only help you design features, it also makes other work easier.

Taking over a feature or working on a new part of a project is easier when you know what data to expect. You won’t have to check the database or log the object to know what is stored in it anymore. It’s as simple as opening the object definition!

Defining data models acts as sort of documentation - scarce but can provide some insights. This is useful for collaborative or solo work, as it does come back to the project less painful.

IDE/Text Editor’s Integration

As shown in the above GIF, IDE loves TypeScript. They will suggest attributes and methods depending on the type of the object you’re accessing.

This is something popular libraries provided for quite some time, but having it for your own code is quite fantastic and a real-time saver. As it has been said, this helps you focus on what matter, implementing features. You shouldn’t have to worry about method’s attribute.

Subscribe to the newsletter to get new articles right in your inbox!

Subscribe to the newsletter

Using TypeScript makes you a TypeScript developer?

Before diving into some downsides of TypeScript, I wanted to address this question. Will using TypeScript makes you a TypeScript develop? The answer, in my opinion, is not as straightforward as it could appear.

I would say that, depending on what you build using TypeScript, you can call yourself a TS developer. Building a simple front end, only using TS for type definition, won’t make you a TypeScript dev. It will make you a better JavaScript developer.

I don’t mean that in a pejorative way, in my opinion, you should use TypeScript regardless of the size of the project. However, TS types offer way more to simple interfaces to model your data.

People building libraries that have complete TS support are the one that can be called TypeScript developer. They have a deep understanding, and that’s the key difference.

Theo (CEO of ping.gg) put things perfectly in a recent video where he reacted at a talk given by the react-table creator.

I came to the realization that I’m still miles away of being a great TypeScript developer when I decided to try my hands at the type challenge. I wasn’t able to complete the first challenge, which asks you to replicate the behavior of the Pick method.

Here is the solution of the first challenge, not as impressive once you see it, but I wasn’t able to come up with this. Hopefully, Matt Pocock started a series where he solves those challenges.

type MyPick<T, K extends keyof T = keyof T> = {
  [P in K]: T[P]
}

TypeScript downsides

Pug in a blanket
Photo by Matthew Henry / Unsplash

As for everything, TypeScript isn’t a bullet-proof solution, and it still has some downsides.

The 'any' type

First, there is the any type that says to TypeScript that the data can be anything and that we can do whatever we want with it. I have a hard time to come up with a reason to have any in a project. It could be useful for quick testing before properly typing a file, but why not do things right the first time? I would recommend avoiding using the any type as possible.

Too Much Code to Write

One might fear that having to type everything is too cumbersome. That the code will become verbose and hard to read. This is true to some extent, since declaring an attribute or a method can be lengthy.

However, there is some type definition that can be shortened since the value is inferred. For example, no need to define the type of store if it’s directly initialized with a value.

//Both solutions are the same, one is easier to read
const [a, setA] = useState<string>('')
const [b, setB] = useState('')

The way you write your code will also have an important effect on how readable it is. Declaring an interface when building a React component (or a method) improve readability.

Destructuring both the props and the type definition in the method declaration will result in a messy code, as shown in the following example.

interface Props {
  label: string
  onClick: () => void
}

const Button = ({ label, onClick }: Props) => {
  return (
    <button
      className="bold rounded-lg bg-emerald-400 p-3 font-default tracking-wide text-white"
      onClick={onClick}>
      {label}
    </button>
  )
}

//This is messy and hard to read
const Button2 = ({
  label,
  onClick,
}: {
  label: string
  onClick: () => void
}) => {
  return (
    <button
      className="bold rounded-lg bg-emerald-400 p-3 font-default tracking-wide text-white"
      onClick={onClick}>
      {label}
    </button>
  )
}

Constructor for Objects

Dealing with classes and constructor can be painful. Especially when you’re a lot of different models and / or a lot of properties. Building classic TS classes require the implementation of a constructor, validating the values, and passing the attributes to the constructor.

I don’t know how this can be improved without resorting to using a third party library. That’s at least the solution I use and like. Zod is a schema validation library, but can be used for parsing data to an object.

Since it’s primarily used for validating schema, Zod came with plenty of methods to make sure you have the correct data. Whether you need to have a number smaller than 10000, a string composed of 12 chars, an email or a URL, Zod have you covered.

You can see how the code is different between those two methods, I’d much rather use the Zod approach since it handles things for me.

import z from "zod"

class User {
  constructor(
    public userName: string,
    public firstName: string,
    public lastName: string
  ) {}
}

//Creating using the class
const classicMethod = (data: any) => {
  //TODO validate data
  return new User(data.userName, data.firstName, data.lastName)
}

const UserParser = z.object({
  userName: z.string(),
  firstName: z.string(),
  lastName: z.string(),
})

//This makes it possible to use the object throughout the project
type UserType = z.infer<typeof UserParser>

//Creating using zod, will throw an error if data isn't correct
const zodMethod = (data: any) => {
  return UserParser.parse({ ...data })
}

Other

There are certainly plenty of complaints that can be done against TypeScript.  Some might not like the fact that Microsoft is behind the project, or find that it doesn’t solve the issue it promises to.

They are all fair points, and I don’t want to mock people using JavaScript. The goal is to explain why you might want to consider TypeScript for your next project.


How to Start Using TypeScript

TypeScript can be set when creating a new project. Both create-react-app and create-next-appsupports TS. Simply add the TypeScript parameter to the command and everything will be done for you.

//For React
npx create-react-app my-app —template typescript

//For Next
npx create-next-app@latest --ts

You can also add TypeScript to an existing project and gradually adopt the language. If that’s the case, look at the documentation related to your framework to see how you can do so. It’s often as simple as adding TypeScript and types as dependencies and create a tsconfigfile.

How to Quickly Create Type for Remote Data

Creating an interface out of the response of an API is a pain. You have to make the query, print the value and create the interface. Hopefully, there is a method that is way easier and that can reduce this time to a matter of seconds and from VS Code.

Simply subscribe to the newsletter to see how this can be done!

This post is for subscribers only

Already have an account? Sign in.