DEV Community

Cover image for How to Learn and Use TypeScript: A Comprehensive Beginner's Guide
Brian Schnee
Brian Schnee

Posted on • Updated on

How to Learn and Use TypeScript: A Comprehensive Beginner's Guide

In this article, I will provide tools and a mental framework to help you effectively learn and work with TypeScript. I will show you that learning TypeScript from a JavaScript background is more manageable than it may seem. To achieve this, we will begin by understanding the foundational types, but with a slightly different approach emphasizing practical application. Finally, I will share tips and tricks I have picked up through experience that you won't find anywhere else.

This is a comprehensive resource aimed to be the last resource you will ever need to start using TypeScript. As such, I recommend breaking up your time reading this article into chunks. The following sections will provide information I wish I had known when first learning to use TypeScript.

Please enjoy!

Table of Contents

  1. How To Learn TypeScript
  2. Understanding Type Safety
  3. The Types You Need
  4. Benefiting From Your Coding Environment
  5. How to Read Error Messages
  6. Using TypeScript in a Project Environment
  7. Conclusion

How To Learn TypeScript

Mastering TypeScript requires more than just learning its syntax. Knowing the types is a meaningful step, but most importantly, it is how to understand the patterns of our code. Please be aware that TypeScript is a development aid but should not be seen as the sole code we are writing. Most of our coding is still plain old JavaScript with stated expectations.

Note: All JavaScript is valid TypeScript. Once you transpile your code, all of your TypeScript will become JavaScript. More on this later.


Understanding Type Safety

TypeScript prevents us from assigning values of the wrong type to a variable; this is called type safety. In TypeScript, we can declare the type of a variable, which helps to ensure that the variable only holds values of that specific type throughout the lifetime of our application.

By enforcing type safety, TypeScript can catch potential errors early in the development process, leading to more reliable and robust code. This also means that, compared to JavaScript, we can often prevent runtime errors that users may have otherwise encountered.

The types we'll cover will be familiar terms, such as number, string, boolean, array, and object. The critical difference is that TypeScript provides a way to ensure the validity of our values in real-time. In contrast, JavaScript lacks such a mechanism, making it tedious and sometimes difficult to guarantee the correctness of values without writing conditions and boilerplate code.

Take a look at the JavaScript example below. To verify that every element of the numbers array is a number, we need to add a check that runs during every iteration.

JavaScript boilerplate

Although that wasn't too bad, did you notice that the numbers parameter was never validated as an array? It's easy to miss potential problems in our code.

Let's see how we can avoid manually testing edge cases in the next section.


The Types You Need

I've decided to create a separate article for this section, so those who feel comfortable with the material can move on easily. And, for those who want to revisit the recommended types later, it'll now be easier to explore.

If you're new to TypeScript or want a refresher on the most commonly used types, head over to The Types You Need, where we'll continue from where we left off and learn about the following types: number, string, boolean, any, unknown, const, unions, undefined, null, arrays, objects, parameters, return types, void, methods, generics, custom types and intersections. From there, you will be led back to this article where I encourage you to continue learning. Thank you!


Benefiting From Your Coding Environment

TypeScript offers more than just error detection and correction. By leveraging TypeScript's type system and writing clean, reusable code, you can build an environment that helps you write better code. TypeScript can identify potential problem areas in your code and suggest solutions, allowing you to avoid errors and write code that is easier to maintain.

Program Predictive Behavior

To make the most of TypeScript, it's essential to define the behavior you want to use and follow it throughout development. By extracting repeating code into types and clearly stating your intentions for variables and returns, TypeScript can help guide you toward the right solution. With TypeScript's help, you can write correct, easy-to-read, and maintainable code.

Let TypeScript Guide You

TypeScript's powerful type system provides you with immediate feedback on potential issues in your code. If you try to assign a value of the wrong type to a variable, TypeScript will generate an error message and show a squiggly line under the offending code. Following TypeScript’s guidance can make you a more efficient and productive developer.

Improved Developer Experience

TypeScript significantly improves your developer experience by providing tools that help you write better code faster. Its editor integration offers intelligent code completion, navigation, and refactoring, allowing you to write more confidently and accurately. TypeScript's strict type-checking identifies potential issues in your code early on, giving you more time to build new features instead of fixing bugs. This type of safety also works across your entire project, ensuring consistency and reducing the risk of errors. Additionally, TypeScript's support for modern ECMAScript features allows you to use the latest language features while maintaining compatibility with older browsers.


How to Read Error Messages

Understanding error messages in TypeScript can be challenging, but with practice, it becomes easier. To begin with, it is crucial to understand the expectations of the code you use, which means knowing the expected types of variables, functions, and values.

When you encounter a type error, it can happen in one of two ways:

  1. When you attempt to use a variable, function, or value in a way that breaks its type contract.
  2. When TypeScript needs more information about what you're trying to do to be confident about the behavior.

TypeScript will provide an error message to help you understand both cases’ issues.

To become proficient at understanding error messages, you need to become familiar with the typical patterns of errors that occur. This familiarity will help you recognize pitfalls as they happen, making it easier to debug your code.

For better assistance in reading error messages, you can download the VSCode extension Total TypeScript by Matt Pocock. This extension includes an error translator that converts TypeScript error messages into a more human-readable format.

Common Errors and Why They Happen

While reading through this section, I encourage you to click on the example code and try to solve the type errors. You will have succeeded when the error messages go away. Good Luck!

Type 'x' is not assignable to type 'y': This error occurs when you try to assign a value of a different type to a variable than the type the variable was defined with.

Example of the Error Message: Type 'x' is not assignable to type 'y'

Example of the Error

Solution: Change your code to follow or redefine the type contract.


Property 'x' does not exist on type 'y': This error occurs when you try to access a property that does not exist on an object.

Example of the Error Message: Property 'x' does not exist on type 'y'

Example of the Error

Solution: The error message will include the shape of the object you are trying to access a property from. Read the definition and make sure to use properties that exist within the type.

Tip: When you type '.' on an object, TypeScript will show you the methods and properties that belong to the object.


Cannot find name 'x': This error occurs when you try to use a variable or name that has not been declared or is not accessible in the current scope.

Example of the Error Message: Cannot find name 'x'

Example of the Error

Solution: Define the variable you are trying to use, consider the scope, and check your spelling.


Parameter 'x' implicitly has an 'any' type: This error occurs when you do not explicitly declare the type of a function parameter and TypeScript cannot infer it.

Example of the Error Message: Parameter 'x' implicitly has an 'any' type

Example of the Error

Solution: TypeScript would like to know more about the usage of your variable. In this case, create a type based on what behavior you want. You can type an element explicitly as 'any’, but it is generally unadvised for most cases.


The left-hand side of an arithmetic operation must be of type 'any’, 'number', 'bigint' or an enum type: This error occurs when you try to perform an arithmetic operation on a value that is not a number or a BigInt.

Example of the Error Message: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type

Example of the Error

Solution: Verify that you are performing proper operations for each type. In certain cases, you can cast a value to the right type.


Object is possibly 'null' or 'undefined': This error occurs when trying to access a property or method on an object that may be null or undefined.

Example of the Error Message: Object is possibly 'null' or 'undefined'

Example of the Error

Solution: Add type checking before you use properties on a potentially null or undefined object through conditionals.

Tip: You can alternatively use JavaScript's optional chaining operator ?., or in certain cases, TypeScript's Non-null assertion operator ! (use with caution) to verify that an object is neither undefined nor null and keep your code concise.


Using TypeScript in a Project Environment

Now that we have introduced a collection of types, using TypeScript to our benefit and standard errors, let's learn how to use TypeScript within a project environment. Throughout this section, I will show you how to use TypeScript within a Node.js environment.


Basic TypeScript Project Structure

In TypeScript projects, keeping all your code in a directory called src located at the root of your project is typical. Similarly, all files and folders related to your project's creation and configuration should be kept at the root level. Here's an example:

node_modules/
src/
   |_ all your `.ts` files in here
.gitignore
package-lock.json
package.json
tsconfig.json
Enter fullscreen mode Exit fullscreen mode

What do I do with the tsconfig.json?

When I first began using TypeScript, I struggled to find comprehensive guidance on structuring my tsconfig.json file. This file defines the rules that our TypeScript code should adhere to, including the code it should support, things to check for, how it should be transpiled, and where it should be transpiled.

As a beginner, I suggest keeping it simple. When you continue to work with TypeScript, you will find rules that match your needs. For now, don't stress over it; there are no perfect rules.

The easiest option is to use the following command to generate a template for you.

tsc --init
Enter fullscreen mode Exit fullscreen mode

If you do not have TypeScript globally installed, use npx tsc --init

This command will generate a tsconfig.json file with potential rules that can be turned on (by uncommenting). Due to the number of rules, I find it easier to work from a less daunting template that allows you to find and add rules iteratively.

Visit Compiler Options to find rules that match your needs.

Starter Template

Let's replace the contents of the tsconfig.json file with our own rules:

// tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

How to Run Your Code?

At some point, our TypeScript code must transpile into JavaScript to be run and understood by node or our browser. Transpilation is when one language is translated into another.

Usually, TypeScript tutorials start by showing us how to transpile our code with tsc, but I will be providing other options that I tend to prefer.

Note: There are many different ways to run TypeScript; what you choose will primarily be based on performance within your workspace.

Using node

The easiest way to execute your code is by running the node command followed by the root file of your project. This command will both transpile and execute your code.

node src/index.ts
Enter fullscreen mode Exit fullscreen mode

Note: You can install the nodemon package to automatically re-execute on change. However, we will cover how to use ts-node-dev, which is what I prefer.

Using ts-node-dev

I recommend using this method for most of your projects, and it’s easy to set up and more performant.

There are ways to make using nodemon performant, but the steps are far more involved than the following:

First, install ts-node-dev as a devDependency.

npm i -D ts-node-dev
Enter fullscreen mode Exit fullscreen mode

Add the following to your package.json scripts. The --respawn flag will re-transpile and execute your project on save.

// pacakage.json
"scripts": {
   "dev": "ts-node-dev --respawn src/index.ts"
},
Enter fullscreen mode Exit fullscreen mode

Run your project

npm run dev
Enter fullscreen mode Exit fullscreen mode

Using TypesSript in your Existing Projects

To start working in a node environment with TypeScript, it's essential to understand how declaration files work. As your project grows and you install dependencies, TypeScript will need type information for each dependency to ensure you can use library code in a type-safe manner. Installing type declarations for your dependencies is usually straightforward: use the following command for each dependency, as the declarations are often already available.

We use the @types/ followed by the dependency’s name.

npm i -D @types/express
Enter fullscreen mode Exit fullscreen mode

Note: Remember to install all TypeScript-related tools as devDependencies.

Tips For Migration

If you would like to use TypeScript in an existing project, it can be tricky to convert your project from a non-type-safe environment to one that is. I recommend making incremental changes in your code base that allow you to increase your TypeScript coverage in your project slowly. Tackle your project in chunks, following our steps for setting up TypeScript and changing .js files to .ts (.jsx to .tsx in React codebases). After converting the files, you will most likely encounter a handful of "errors" that must be corrected. All this is, is TypeScript wanting you to create contracts and state expectations about your code.

Best of luck, and you will find resources in the conclusion that will help you if you get stuck.

Conclusion

"Fin", end of article

You made it! Thank you for spending the time to read what I wrote. If you found this article helpful and enjoyed learning about TypeScript, consider sharing it with others. Feedback and suggestions for future topics are always welcome.

For further TypeScript exploration, I recommend checking out the TypeScript Handbook and Matt Pocock's free beginner tutorials at Total TypeScript. However, you should now have enough exposure to start using TypeScript in your projects.

Sometimes errors may feel overwhelming. I recommend joining the TypeScript Community Discord Server for help with anything and everything TypeScript.

Top comments (2)

Collapse
 
corners2wall profile image
Corners 2 Wall

Also enum type. You can example with this type in doc if u want this

Collapse
 
brianschnee profile image
Brian Schnee

Thank you for your comment! While enums can be used in certain situations, their unpredictable behavior at runtime caused me to exclude them. If you're interested in learning more about this, there's an excellent video by Matt Pocock called Enums Considered Harmful. In my article, I aimed to provide the most commonly used types in TypeScript development, and have chosen to exclude enums and other types that may not be necessary for beginners. However, as one progresses, there may be situations where these types become valuable, and it's always worth exploring different options to find the right fit for your projects. I hope that helps!