01/03/2023

Why is typescript worth it in e-commerce applications?

Author: Dominik

Typescript is enjoying popularity in the frontend as well as in the backend. Typescript is also one of the most in-demand programming languages.

Some people might ask: “Why do I need Typescript features to develop a Frontend app?”.

Common arguments against it are:

  • unnecessary dependencies
  • increases the duration of on-boarding
  • slows down development
  • complicates maintenance

Is reality quite the opposite? Let’s focus on e-commerce apps. Is typescript a good choice?

Why did Javascript need to change?

Bugs will always occur in programming. Often they are caused by an error related to programmers' inaccuracy. One of the most common cases is converting the price of a product including a discount. In Javascript such a function could look like this:

const getRegularPrice = (discountedPrice, discount) => {
  return discountedPrice + discount
}

Imagine that during a promotional event we want to display the regular price next to the current price. Everything works as intended if the values are fed to the function as numbers. What if the function is called with strings instead of numbers?

const regularPrice = getRegularPrice(100, '20') 
// regularPrice is equal 10020 

We can expect customers to be confused. If users see a miscalculated price, they will not want to risk a purchase if they are unsure of the price because if such a situation happens at checkout, we expose the user to additional costs or our own losses.

The Typescript approach

The above example for Javascript is correct. Javascript doesn’t support static typing. It doesn't know that you want to add two numbers, so unexpected results can happen. We can easily add types to our function:

const getRegularPrice = (discountedPrice: number, discount: number) => {
  return discountedPrice + discount 
}

The written function is now much more secure! The use of Typescript prevents the passing of an incorrect argument type to a function.

It helps the developer to have the right workflow

When writing code in statically typed languages, you must think about the types of data you will get and then about the kind of data you want to produce.

I was reminded of one edge case while building a product page. My task was to display the price of a single product when buying a multi-pack (average of all products). The project was created without Typescript. In Javascript, the function that calculates the price of one product might look like this:

const getSingleProductPrice = ( products ) => {
  return products.reduce((a, b) =>  a + b, 0) / products.length 
}

The function works as expected for a product with some variants. However, if the product has no variants, the value displayed in our application is NaN!

getSingleProductPrice([1, 2, 3]) // returns 2
getSingleProductPrice([])  // returns NaN

The error is due to the attempt to divide by 0. For such a case, we want there to be a value in the array. The following product type ensures that we provide at least one value in the array as an argument.

const getSingleProductPrice = (products: [number, ...number[]]) => { 
  return products.reduce((a, b) => a + b, 0) / products.length 
} 

// Argument of type '[]' is not assignable to parameter of type '[number, ...number[]]'   
getSingleProductPrice([])   

If an empty array is specified, Typescript will protect us from an incorrect value. Typescript encourages you to think about the interface of your code before starting the implementation. I think that for this project, using this approach with Typescript would have avoided tedious debugging.

Units matter

Suppose that in our application we receive the shipping price in dollars from an external service. On the other hand, we have the product price in euros from our internal service. We want to avoid wrong operations with these units. Although both are represented as "number", we cannot use them in the same way. In Javascript there are numbers and they cannot be distinguished, the responsibility for distinguishing the units lies with the programmer.

However, there is no official solution to this problem in Typescript either.

When using Typescript, we mostly use structured types. This means that types are compared based on their content (the same definitions of fields and methods).

We can use nominal types – it means that we can indicate to the compiler that types are different from each other, even if they are equivalent to other types. There is no official support in Typescript. However, there are some methods that allow you to solve this problem independently.

Below I show an example from this article, there are several ways to use structural type implementations. This example seems clear at first glance:

declare const __nominal__type: unique symbol 

export type Nominal<Type, Identifier> = Type & {
  readonly [__nominal__type]: Identifier
}

type EUR = Nominal<number, 'EUR'>
type USD = Nominal<number, 'USD'>     

After we have type definitions for our units, we can define type constructors to concentrate type-casting in one place

const eur = (amount: number) => amount as EUR  
const usd = (amount: number) => amount as USD

const productPrice = eur(100)
const shippingPrice = usd(10) 

As you can see, this is an easy way to gain control over the units in our application!

Think about the Developer Experience

In dynamically typed languages (Javascript), when working with new code (or code we haven't seen in a long time), it is very often difficult to answer what arguments a function accepts or what it returns. In a statically typed language (Typescript), you get answers to the above questions right from within your IDE and compiler.

A common argument against Typescript is the time it takes to introduce new developers to the project. Typescript's syntax is intuitive and very easy to understand - if a programmer is proficient in Javascript, switching to TS will not be a problem. Also, if you have already created a project in Typescript, it's easy for new developers to get into it. When a programmer needs to change a small thing or implement something new, he or she no longer needs to search through all the code to understand what data is passed.

Conclusion

To answer the title question - yes, it is worth it! I agree that developing code in Typescript will initially take more time, it also has a minimally higher entry threshold. If you are building a new frontend application that will be maintained over time and developed by other developers, you should rely on Typescript. Typescript will definitely facilitate the development of the project in future iterations.

Related Posts

Contact with: Dominik