Typescript

How to create custom types in TypeScript? 

There are numerous methods for improving your code’s readability, maintainability, and extensibility. Clean Code principles must be followed, as well as various...

Written by Luci · 2 min read >

There are numerous methods for improving your code’s readability, maintainability, and extensibility. Clean Code principles must be followed, as well as various architectures, letter casing rules, and so on. Using types is still, in my opinion, one of the best ways to write great code.

I’m pretty sure you’re already familiar with TypeScript’s basic types like number :

const hoursOfCoding: number = 8

or string :

const favouriteQuote: string = ‘Fortune favors the prepared mind.’

or array :

const bestGames: string[] = [‘Guitar Hero’, ‘Mortal Kombat’, ‘Need for Speed’]

and so on.

This is an easy and clear convention to follow with simple variables and small school projects. Now let’s say we’re working with an API that responds with a more complex structure, like this:

User
{
  id: 3601,
  name: 'John Doe',
  yearOfBirth: 1992,
  favouriteMovies: ['Home Alone', 'E.T.', 'Die Hard']
  orders: [
    {
      id: 234,
      title: 'Home Alone',
      price: 99,
      currency: 'USD',
      onSale: true
    },
    {
      id: 235,
      title: 'Forrest Gump',
      price: 199,
      currency: 'USD',
      onSale: false
    }
  ]
}

When we use a particular service or make an API call, the response will always follow the same pattern. The user in our example will always have an id, a name, a birth year, and so on, so we should create a custom type for this. Not only because it’s a great feeling to put the pieces of the application together, but because later the editor will assist us with beautiful error messages like

Property 'yearOfBirth, ...' is missing in type '{ name: string; }' but required in type 'User'.

so we will be able to easily figure out how to build a service function that returns a user.

Alright, let’s get into it.

Creating a new custom type is really easy, just use the type word to declare it.

type User

Please be aware that the naming convention used here is UpperCamelCase. The next thing to consider is the outermost layer of our value, which in this case is an object:

type User = {}

Our custom type is now ready to use; the editor will not give us an error message if we try to declare a variable with it but let’s improve it. The next step is to collect and categorize all of our object’s basic type fields:

type User = {
  id: number,
  name: string,
  yearOfBirth: number,
  favouriteMovies: string[]
}

Almost there! Now, we can see that the orders is an array of custom-type objects as well. In this case, we should take advantage of TypeScript’s use-case of array types like string[] (an array that contains string values) or number[] (contains number values) and create an Order type and use it the same way: Order[]

type Order = {
  id: number,
  title: string,
  price: number,
  currency: string,
  onSale: boolean
}

And that is basically it. We have two fully customized types ready to use

type Order = {
  id: number,
  title: string,
  price: number,
  currency: string,
  onSale: boolean
}
type User = {
  id: number,
  name: string,
  yearOfBirth: number,
  favouriteMovies: string[],
  orders: Order[]
}

and we can easily type our variable

const userToHandle: User = {
  id: 3601,
  name: 'John Doe',
  yearOfBirth: 1992,
  favouriteMovies: ['Home Alone', 'E.T.', 'Die Hard']
  orders: [
    {
      id: 234,
      title: 'Home Alone',
      price: 99,
      currency: 'USD',
      onSale: true
    },
    {
      id: 235,
      title: 'Forrest Gump',
      price: 199,
      currency: 'USD',
      onSale: false
    }
  ]
}

or later any other user-related variable and state with them.

Optional fields

If you have a property that can be attached to your entity later on a condition, you can use the ? operator to create optional fields; in our example, on the user object the orders or favouriteMovies fields could be undefined if the user has not ordered anything yet, so the type must be constructed to work without favouriteMovies and orders fields as well like this:

type User = {
  id: number,
  name: string,
  yearOfBirth: number,
  favouriteMovies?: string[],
  orders?: Order[]
}

In this case, the user object can be constructed and will be defined without the optional fields as well.

Pipe operator

Assume that some orders have a number and others have a string type id. You can always use the good old any type

{
  id: any
  ...
}

but that isn’t very professional.

The best solution is to type the id field using the pipe operator | because it can be either a number OR a string :

type Order = {
  id: number | string,
  title: string,
  price: number,
  currency: string,
  onSale: boolean
}

Now id is able to be a number like 234 or a string like 'cf41e5bd’ .

Written by Luci
I am a multidisciplinary designer and developer with a main focus on Digital Design and Branding, located in Cluj Napoca, Romania. Profile

How To Create A Queue In TypeScript?

Luci in Typescript
  ·   1 min read
0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x