Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Full-Stack React, TypeScript, and Node
Full-Stack React, TypeScript, and Node

Full-Stack React, TypeScript, and Node: Build scalable and cloud-ready web applications using React 19, TypeScript, and Docker , Second Edition

Arrow left icon
Profile Icon David Choi
Arrow right icon
Early Access Early Access Publishing in Sep 2025
$19.99 per month
Paperback Sep 2025 407 pages 2nd Edition
Subscription
Free Trial
Renews at $19.99p/m
Arrow left icon
Profile Icon David Choi
Arrow right icon
Early Access Early Access Publishing in Sep 2025
$19.99 per month
Paperback Sep 2025 407 pages 2nd Edition
Subscription
Free Trial
Renews at $19.99p/m
Subscription
Free Trial
Renews at $19.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. €18.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

Full-Stack React, TypeScript, and Node

1 Understanding TypeScript

JavaScript is an enormously popular and powerful language. According to GitHub’s State of the Octoverse 2022, it is the most popular language in the world. However, for large application development, its feature set is considered incomplete, and this is why TypeScript was created.In this chapter, we'll learn about the TypeScript language, why it was created, and what value it provides to JavaScript developers. We'll learn about the design philosophy Microsoft used in creating TypeScript and how these design decisions added important features for large application development.We'll also see how TypeScript enhances and improves JavaScript. We'll compare and contrast the JavaScript way of writing code with the way code is written in TypeScript.TypeScript has a wealth of cutting-edge features to benefit developers. Chief among them are static typing and Object-Oriented Programming (OOP) capabilities. These features can help make code that is higher quality and easier to maintain.By the end of this chapter, you will understand how TypeScript provides additional features on top of JavaScript and makes writing large, complex applications easier and less prone to error.In this chapter, we're going to cover the following main topics:

  • What is TypeScript?
  • Why is TypeScript necessary?

Technical requirements

To take full advantage of this chapter, you should be an intermediate developer experienced in coding with another type-safe language and platform. You'll also need to install Node and a JavaScript code editor, such as Visual Studio Code (we’ll walk through the setup of our development environment together).You can find the GitHub repository for this chapter at https://github.com/PacktPublishing/Full-Stack-React-TypeScript-and-Node-2nd-Edition. Use the code in the Chap1 folder.

What is TypeScript?

TypeScript is actually two distinct but related technologies – a language and a compiler:

  • The language is a feature-rich, statically typed programming language that adds true object-oriented capabilities to JavaScript.
  • The compiler converts TypeScript code into native JavaScript, but also provides the programmer with guidance in the form of errors during development.

TypeScript enables the developer to design software that's of higher quality. By using TypeScript, a developer can write code that is easier to understand and refactor and contains fewer bugs. Additionally, it adds discipline to the development workflow by forcing errors to be fixed while still in development. I will show you examples of these important TypeScript capabilities as we proceed with the chapter.TypeScript is a development-time technology. There is no runtime component, and no TypeScript code ever runs on any machine. Instead, the TypeScript compiler converts TypeScript into JavaScript, and that code is then deployed and run on browsers or servers.So then, if TypeScript has no runtime, how do developers get running code? TypeScript uses a process called transpilation. Transpilation is a method where code from one language is "compiled" or converted into another language. This is in contrast to standard software compilation, where code is converted into a binary representation that is intended to be run on the destination machine. The transpilation process does not result in a binary file, but an entirely different language. It is then this language that is ultimately run.Now that you know what TypeScript is. In the next section, we'll learn about why these features are necessary for building large, complex applications.

Why is TypeScript necessary?

The JavaScript programming language was created by Brendan Eich and added to the Netscape browser in 1995. Since that time, JavaScript has enjoyed enormous success and is now used to build servers and desktop apps as well. However, this popularity and ubiquity have turned out to be a problem as well as a benefit. As larger and larger apps have been created, developers have started to notice the limitations of the language.Large application development requires more sophisticated language features than the browser development JavaScript was first created for. In general, almost all large application development languages, such as Java, C++, C#, and so on, provide static typing and OOP capabilities.In this section, we'll go over the advantages of static typing over JavaScript's dynamic typing. We'll also learn about OOP and why JavaScript's method of doing OOP is too limited to use for large apps. But first, we'll need to install a few dependencies and programs to allow our examples to run. To do this, follow these instructions:

  1. Let's install Node first. Node is a JavaScript runtime. It allows us to run JavaScript code outside of a browser. But Node also gives us npm, Node Package Manager, which is a JavaScript dependency manager that will allow us to install TypeScript as well as other dependencies. If you’re familiar with Maven or Nuget it’s effectively the same thing. We'll dive deep into Node in Chapter 8, Learning Server-Side Development with Node.js and Express. You can download Node from here: https://nodejs.org/. Please install version 323 or higher.
  2. Install VSCode. It is a free code editor and its high-quality and rich features have quickly made it the standard development application for writing JavaScript code on any platform. You can use any code editor you like, but I will use VSCode extensively in this book.
  3. Create a folder in your personal directory called FullStackTypeScript. We'll save all our project code in this folder.
  4. Inside FullStackTypeScript, create another folder called Chap1.
  5. Open VSCode and go to File | Open, and then open the Chap1 folder you just created. Then, select View | Terminal and enable the terminal window within your VSCode window.
  6. Type the following command into the terminal. This command will initialize your project, by creating a file called package.json, so that it can accept npm package dependencies. You'll need this since TypeScript is downloaded as a npm package:
npm init

npm is the main command, and whatever comes after can be thought of as parameters. You should see a screen like this:

Figure 1.1 – npm init screen

Accept the defaults for all the prompts, as we will only install TypeScript for now.

  1. If you now open package.json you will see something like this:
{
  "name": "chap1",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "dependencies": {
  
  }
}

Most of the fields are self-explanatory, but notice we have a section called scripts. This is where we would create scripts that we use to build, test, and execute our project. For this simple example, we will not use this section, but we will use it extensively in later chapters. Additionally, lower down, you can see the dependencies section, which refers to dependency packages our project needs.

  1. Now, normally in a real project, I would install TypeScript with the following command:
npm install typescript

npm install is the command that installs packages locally to the project. However, in this case, we will install TypeScript globally to make things a bit easier to use for these simple examples. So then write this command and execute it:

npm install –g typescript

As you can see, we have added the –g parameter, which will cause TypeScript to be installed globally on the machine and make it available anywhere on the command line. Note that if you are running a Mac, you will probably need to enter sudo in order to install TypeScript globally.

IMPORTANT NOTE

If you are already familiar with npm and have previously installed TypeScript globally, you must update your version to at least 5.5 or later.

After all the items have been installed, your VSCode screen should look like this:

Figure 1.2 – VSCode after setup is complete

We've finished installing and setting up our environment. Now, we can take a look at some examples that will help us better understand the benefits of TypeScript.

Dynamic versus static typing

Every programming language has and makes use of types. A type is simply a set of reusable rules that describe an object or variable. JavaScript is a dynamically typed language. In JavaScript, new variables do not need to declare their type, and even after they are set, they can be reset to a different type. This feature adds awesome flexibility to the language, but it is also the source of many bugs.TypeScript takes the alternative route and uses static typing. Static typing forces the developer to indicate the type of variable up front, when they create it. This removes ambiguity and eliminates many conversion errors between types. In the following examples, we'll take a look at some of the pitfalls of dynamic typing and how TypeScript's static typing can eliminate them:

IMPORTANT NOTE

It is very important that you write out the code from scratch and try not to rely solely on the existing project files. Writing code yourself and attempting to run it will be the best way to learn.

  1. On the root of the Chap1 folder, let's create a file called string-vs-number.ts. The .ts file extension is a TypeScript-specific extension and allows the TypeScript compiler to recognize the file and transpile it into JavaScript.
  2. Next, enter the following code into the file and save it:
let a = 5;
let b = '6';
console.log(a + b);

The code is very simple. We declared two variables a and b, and give them values. Then we print the sum of those values using console.log, which is the function that allows printing to the terminal or browser console.

  1. Let’s now transpile the code into JavaScript. In the terminal, type the following:
tsc string-vs-number.ts

tsc is the command to execute the TypeScript compiler, and the filename tells the compiler to check and transpile the file into JavaScript.

  1. Once you run the tsc command, you should see a new file, string-vs-number.js, in the same folder. This is the transpiled JavaScript file. Let's run this file with the following command:
node string-vs-number.js

The node command acts as a runtime environment for the JavaScript file. In other words, it interprets the JavaScript inside the .js file and executes it. We’ll learn much more about Node in Chapter 8, Learning Server-Side Development with Node.js and Express. Once you have run this script, you should see this:

56

Obviously, if we add two numbers together normally, we want a sum to happen, not a string concatenation. However, since the JavaScript runtime has no way of knowing this, it guesses the desired intent and converts the number variable into a string, and appends variable b to it.

  1. Let's introduce TypeScript's static typing into this code and see what happens. Take a look at the updated code:
let a: number = 5;
let b: number = '6';
console.log(a + b);

As you can see, we’ve added “: number” after each variable. This syntax is called Type Annotation. And we are explicitly using it to indicate to TypeScript what type these variables should be.

  1. If you run the tsc compiler on this code, you will get the error Type 'string' is not assignable to type 'number'. This is exactly what we want. The compiler tells us that there is an error in our code and prevents the compilation from completing successfully.
  2. Since we indicated that both variables are supposed to be numbers, the compiler checks for that and complains when it finds it not to be true. So, if we fix this code and set b to be a number, let's see what happens:
let a: number = 5;
let b: number = 6;
console.log(a + b);
  1. Now, if you run the compiler, it will complete successfully, and running the JavaScript will result in the value 11 as shown here:
Figure 1.3 – Valid numbers addition

Great, we now know when we make these kinds of typing errors, TypeScript will catch our error and prevent it from being used at runtime.Let's look at another more complex example:

  1. Create a new .ts file called test-age.ts and add the following code to it:
function canDrive(usr) { 
    console.log("user is", usr.name);  
 
    if (usr.age >= 16) {
        console.log("allow to drive");
    } else {
        console.log("do not allow to drive");
    }
}
 
const tom = {
    name: "tom"
}
canDrive (tom);

As you can see, the code has a function that checks the age of a user and determines, based on that age, whether they are allowed to drive. However, after this function definition, we see that a user is created but with no age property. This would become an issue when running the canDrive function, since Tom’s age property would be undefined. An undefined usr.age conditional statement would resolve to false. This behavior is known as being falsy in JavaScript. Note, we’ll learn about JavaScript’s falsy feature as well as many other important JavaScript capabilities in Chapter 3: Building Better Apps with ES6+ Features. In the case of this example, if it turned out that the user tom was over 16 years old our canDrive function would run the wrong statement and cause a bug.There are ways in JavaScript to deal with this problem, at least partially. We could use a for loop to iterate through all of the property key names of the user object and check for an age name. Then, we could throw an exception or have some other error handler deal with this issue. However, if we had to do this on every function, it would become inefficient and onerous very quickly. Additionally, we would be doing these checks while the code is running. Obviously, for these errors, we would prefer to catch them before they reach users. TypeScript provides a simple solution to this issue and catches the error before the code even makes it into production. Take a look at the following updated code:

interface User {
    name: string;
    age: number;
}
 
function canDrive(usr: User) {  
    console.log("user is", usr.name);  
 
    if(usr.age >= 16) {
        console.log("allow to drive");
    } else {
        console.log("do not allow to drive");
    }
}
     
const tom = {
    name: "tom"
}
canDrive (tom);

Let's go through this updated code. At the top, we see something called an interface, and it is given the name of User. I'll detail interfaces and other types in later chapters, but for now, we can say an interface is a type without an implementation, otherwise known as a contract.The User interface has the two fields that we need: name and age. In other words, any object that is of type User must have those two fields.Now, below that, we see that our canDrive function's usr parameter has a type of User. And this, of course, tells the compiler only to allow parameters of the User type to be given to canDrive. Therefore, when I try and compile this code, the compiler complains that when canDrive is called, age is missing from the passed-in parameter tom-- because it does not have that field:

Figure 1.4 – canDrive error
  1. Once again, the compiler has caught our error. Let's try fixing this issue by giving tom a type, without adding the age property:
const tom: User = {
    name: "tom"
}

If we give tom a type of User, but do not add the required age property, we get the same error:

Property 'age' is missing in type '{ name: string; }' but required in type 'User'.ts(2741)

Clearly, we still have the same issue. So then, let’s add the missing age property, and we should now see that the error goes away and our canDrive function works as it should. Here's the final working code:

interface User {
    name: string;
    age: number;
}
  
function canDrive(usr: User) {   
    console.log("user is", usr.name);   
  
    if(usr.age >= 16) {
        console.log("allow to drive");
    } else {
        console.log("do not allow to drive");
    }
}
  
const tom: User = {
    name: "tom",
    age: 25
}
canDrive (tom);

This code provides the required age property in the tom variable so that when canDrive is executed, the check for usr.age is done correctly and the appropriate code is run.Here's a screenshot of the output once this fix is made and the code is run again:

Figure 1.5 – canDrive successful result

In this section, we learned about some of the pitfalls of dynamic typing and how TypeScript’s static typing can help protect against those issues. Static typing removes ambiguity from code, both to the compiler and other developers. This clarity can reduce errors and make for higher-quality code.In the next section, we will introduce object-oriented programming. This is a commonly used programming methodology that helps improve code quality.

Object-oriented programming

JavaScript is known as an Object-Oriented Programming language. And it does have some of the capabilities of other OOP languages. However, JavaScript's implementation is limited when compared to TypeScript. In this section, we'll take a look at how JavaScript does OOP and how TypeScript improves upon JavaScript's capabilities.First, let's list the four pillars of Object Oriented Programming. There are four major principles of OOPi:

  • Encapsulation
  • Abstraction
  • Inheritance
  • Polymorphism

Let's review each one.

Encapsulation

An easier phrase for understanding encapsulation might be information hiding. In every program, you will have data and methods that allow you to do something with that data. When we use encapsulation, we are taking that data and putting it into a container of sorts. This container is known as a class in most programming languages, and basically, it protects that data so that nothing outside of the container can directly modify or view it.If you want to make use of the data, it must be done through methods that are controlled by the container object. This style of working with object data allows strict control of what happens to that data from a single place in code, instead of being dispersed through many locations across an application.The syntax for controlling information access, of course, varies across languages, but in TypeScript, this syntax is called Accessors. For example, the private accessor only allows members to be accessed by code within the class, and the public accessor allows any code outside or inside the class to modify the affected member. Until recently, there was no direct way of creating accessors in JavaScript. If a developer needed to indicate accessibility, they had to use TypeScript syntax to do so or write more involved JavaScript code structures to do so. However, it is now possible to hide members using plain JavaScript by using the # symbol, and we will prefer this JavaScript syntax in the book.

IMPORTANT NOTE

TypeScript attempts to be as close as possible to the current global standard for JavaScript, known as ECMAScript. Having said that, sometimes TypeScript syntax will be temporarily different from JavaScript until JavaScript “catches up”. Whenever a change to the JavaScript language overlaps with TypeScript’s features, in this book, we will prefer the standard JavaScript syntax.

Note that in the next section, we will provide some simple examples of OOP in TypeScript. However, in Chapter 2, Exploring TypeScript, we will see more robust examples of TypeScript capabilities, including OOP features. For now, let’s keep things simple so we can focus on the core concepts of OOP.Now let’s look at an example of using TypeScript’s accessors to enable encapsulation.Create a new ts file called encapsulation.ts and add the following code to it:

class Encapsulator {
  private name: string;
  get getName(): string {
    return this.name;
  }
  set setName(name: string) {
    this.name = name;
  }
  constructor(name: string) {
    this.name = name;
  }
}
const encapsulator = new Encapsulator("John");
console.log(encapsulator.name);

Now it’s a bit early to start digging too deeply into this code. However, let’s try and understand what is going on here at least at a basic level. First, when creating any kind of system to hide information, we would need some kind of container. And in this case, that is what our class type Encapsulator, is giving us.Next, we can see we have a single field called name. Now, a class does give us a container, but if we don’t expressly indicate any accessor type on our fields, we end up with public fields by default. Therefore, we use the private keyword to make our field name hidden from the outside world (we’ll use the # accessor in later code, but by using the word private, I am emphasizing its hidden nature).Next, we have decided to use getters and setters, getName and setName, in order to expose access to our name field outside of the class, but only indirectly. This means that we control in what manner our name field is accessed and updated or even if it will be allowed to be updated.Now, in order to create a unique instance of our class, we use the new keyword with the class name like this: new Encapsulator(). If you compile and run this file, you should see something like this.

Figure 1.6 – Encapsulation example

As you can see, since our name field is private, it is not accessible directly from outside of our class instance. Let’s do a small update to fix this and view the name of our Encapsulator instance. At the end of our code, replace encapsulator.name with encapsulator.getName Notice getName has no () appended to it. Now, if we compile and run our code, we should see the name John since that’s what we passed to the class’s constructor. We’ve now used a simple feature of TypeScript to perform Encapsulation and hide internal member information. Don’t worry if not everything is crystal clear right now. As stated earlier, we’ll be diving deep into TypeScript in Chapter 2, Exploring TypeScript. Let’s continue with the next pillar of OOP, Abstraction.

Abstraction

Abstraction is related to encapsulation. When using abstraction, you hide the internal implementation of how data is managed and provide a simplified interface to outside code. Primarily, this is done in order to create "loose coupling" of code. Loose coupling means that code responsible for one set of data is independent and separated from other code. In this way, it is possible to change the code in one part of the application without adversely affecting the code in another part.Abstraction for most OOP languages requires the use of a mechanism to provide access to an object, without revealing that object's internal workings. For most languages, this is called an interface or abstract class. Interfaces are like classes whose members have no actual working code. An abstract class is more flexible; you can have members both with and without an implementation. You can consider them to be a shell that only reveals the names and types of object members, but does not implement how they work. This capability is extremely important in producing the loose coupling mentioned previously and allowing code to be more easily modified and maintained. JavaScript does not support interfaces or abstract classes. TypeScript, however, supports both.Let’s look at a simple example to better understand Abstraction.Create a new file called abstraction.ts and add this code to it:

interface User {
  name: string;
  age: number;
  canDrive();
}
class Person implements User {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  canDrive() {
    console.log("user is", this.name);
    if (this.age >= 16) {
      console.log("allow to drive");
    } else {
      console.log("do not allow to drive");
    }
  }
}
const john: User = new Person("john", 15);
john.canDrive();

Now, in our previous section, we already introduced the concept of an interface with the canDrive example. So, in this code, we are extending that example by fleshing it out a bit more. First, we have our User interface; however, you can see we’ve added an empty function called canDrive. This function has the same signature as our original canDrive function, but is part of the User type. And as you can see, it takes no parameters and returns nothing.Next, we have our class Person. And you can see that when our Person class is declared, it indicates an additional keyword, implements. The keyword implements is telling TypeScript that our class Person is intending to define the implementation, the running code, of the members of User. So then our class Person near the bottom declares canDrive and gives it an implementation. To be clear, we could have given canDrive any implementation we wanted, but in this case, we’ve decided to give it the same implementation as our last example. And then finally we create an instance of Person and call the canDrive function.Now, if you compile and run this code, you will see this:

Figure 1.7 – Abstraction example

The output is basically the same as our prior canDrive example. But by using interfaces, we have now decoupled our code’s implementation from its signature.This is a powerful capability, because we no longer need to write our code for a specific implementation. Instead, we can now write code to just a shell and we can have any implementation we want depending on the situation.

Inheritance

Inheritance is about code reuse. For example, if you needed to create objects for several types of vehicles—car, truck, and motorcycle—it would be inefficient to write distinct code for each vehicle type. It would be better to create a base type that has the core attributes of all vehicles, and then reuse that code in each specific vehicle type. This way, we write some of the needed code only once and share it across each vehicle type. The main feature used to create inheritance structures in both JavaScript and TypeScript is classes.Let’s define a class, as we’ve been referring to classes but haven’t yet defined them. A class is a kind of type that stores a related set of fields (data) and also may have functions called methods that can act on those fields.JavaScript supports inheritance by using a system called Prototypical Inheritance. Basically, what this means is that in JavaScript, every object instance of a specific type shares the same instance of a single core object. This core object is the prototype, and whatever fields or methods are created on the prototype are accessible across the various object instances. This is a good way of saving resources, such as memory, but it does not have the level of flexibility or sophistication of the inheritance model in TypeScript.In TypeScript, classes can inherit from other classes, but they can also inherit from interfaces and abstract classes. We’ve actually already seen the interface form of inheritance in the Abstraction example. We'll dive deep into these features in Chapter 2, Exploring TypeScript, but the point is that TypeScript has a more capable inheritance model than JavaScript. It allows for more kinds of inheritance and, therefore, more ways to reuse code. Let’s look at a single example now.

  1. Let’s create a new ts file called inheritance.ts like this:
class Item {
  id: string;
  description: string;
  price: number;
  getId(): string {
    return this.id;
  }
}
class Bicycle extends Item {
  wheelCount: number;
  getWheelCount(): number {
    return this.wheelCount;
  }
}
const bicycle = new Bicycle();
bicycle.id = "123";
bicycle.description = "Mountain Bike";
bicycle.price = 299.99;
bicycle.wheelCount = 2;
console.log("id", bicycle.getId());
console.log("wheel count", bicycle.getWheelCount());

In this example, we are creating types for a company that sells many different types of products. First, we have a base class called Item that represents the most rudimentary information for all the products that our store sells. In other words, all the items sold by our store will always have this information: id, description, price, and getId. Since this is true, we don’t need to recreate these fields and methods for each new type of item. We can simply reuse them.The definition of the Bicycle type shows us how to reuse the code in the Item type by using the extends keyword. By using this keyword, our Bicycle type does not need to define those members again and simply inherits them. However, since it is a specific item, it has its own members, wheelCount and getWheelCount, which we have also defined.After the definition of our two types, we can see that we create an instance of the Bicycle and set all of its fields, including those defined in the Item type. And we finish by logging the values of id and wheelCount.

  1. If we run this code, you will see this output:
Figure 1.8 – Inheritance example

As you can see, our id and wheelCount values are displayed.

Polymorphism

Polymorphism is related to inheritance. In polymorphism, it is possible to declare an object that is of some base type and then set that variable at runtime to a specific type that inherits from that base type. This technique is useful for scenarios where the specific type to use can only be known at runtime.In the case of JavaScript, there is no direct language support for polymorphism. It is possible to simulate it to some degree, but there is no built-in way of enforcing the specific types to be used. TypeScript, however, can be used to implement Polymorphism. This topic is a bit complex, and we don’t know enough about TypeScript just yet to explore this concept thoroughly. We’ll learn more about TypeScript in Chapter 2, Exploring TypeScript, and then I’ll provide examples for this topic there.

Summary

In this chapter, we introduced TypeScript and learned why it was created. We learned why type safety and OOP capabilities are so important for building large apps. Then, we saw some examples comparing dynamic typing and static typing and saw why static typing is a better way of writing complex code. Finally, we compared the styles of OOP between the two languages and learned why TypeScript has a better and more capable system. The information in this chapter has given us a high-level conceptual understanding of the benefits of TypeScript.In the next chapter, we'll do a deeper dive into the TypeScript language. We'll learn more about types and investigate some of the most important features of TypeScript, such as classes, interfaces, and generics.

Left arrow icon Right arrow icon

Key benefits

  • Master the architecture of React 19 and modern single-page applications (SPAs)
  • Develop a scalable Web API using Node.js, Express, and TypeScript
  • Gain hands-on experience with Docker for containerization and AWS for deployment
  • Learn from new and extensively revised chapters for an updated and thorough understanding

Description

In the fast-paced world of web development, React sets the benchmark for high-performance client-side applications, while Node.js and Express enable scalable server-side solutions and web services. TypeScript enhances JavaScript projects with robustness and maintainability, making it essential for large-scale applications. This second edition provides a hands-on guide to mastering these technologies with new chapters and updated content reflecting the latest industry practices. Start with a solid foundation in TypeScript, building high-quality web applications. Explore React 19, leveraging the latest Hooks API and Redux Toolkit for state management. Transition to server-side development with Express, incorporating modern practices like JWT-based authentication and Prisma ORM for database management. A key addition is Docker, streamlining deployment with containerized applications. Learn to configure Express projects with Docker and deploy to AWS for scalable solutions. Updates include Vitest for testing, new React features like Suspense, and expanded content on Postgres and Prisma ORM. By the end of this book, you will have built and deployed a comprehensive full-stack application, ready for production.

Who is this book for?

This book is designed for experienced developers who are new to full-stack web development. It is ideal for those with production programming experience in any language looking to transition into building full-stack applications using modern web technologies. A good understanding of JavaScript is required.

What you will learn

  • Develop a full-featured online forum application using React and TypeScript
  • Discover TypeScript's key features for improving code quality and maintainability
  • Build React applications using functional components and Hooks
  • Implement state management using Redux Toolkit
  • Set up an Express project with TypeScript and Docker from scratch
  • Manage database interactions using Prisma ORM with Postgres
  • Deploy applications to AWS using Docker
  • Learn from new chapter on JWT-based authentication
  • Benefit from updated chapters on Docker and AWS deployment

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Last updated date : Sep 19, 2025
Publication date : Dec 08, 2025
Length: 407 pages
Edition : 2nd
Language : English
ISBN-13 : 9781803235776
Languages :
Tools :

What do you get with a Packt Subscription?

Free for first 7 days. €18.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Last updated date : Sep 19, 2025
Publication date : Dec 08, 2025
Length: 407 pages
Edition : 2nd
Language : English
ISBN-13 : 9781803235776
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Table of Contents

5 Chapters
Full-Stack React, TypeScript, and Node: Build scalable and cloud-ready web applications using React 19, TypeScript, and Docker Chevron down icon Chevron up icon
1 Understanding TypeScript Chevron down icon Chevron up icon
2 Exploring TypeScript Chevron down icon Chevron up icon
3 Building Better Apps with ES6+ Features Chevron down icon Chevron up icon
4Learning Single Page Application Concepts with React Chevron down icon Chevron up icon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.

Modal Close icon
Modal Close icon