Clean Code with TypeScript....2
Elevate your TypeScript 6 skills with clean code principles and production-ready practices....2
Clean Code with TypeScript....3
Contributors....5
About the authors....5
About the reviewer....6
Table of Contents....7
Preface....21
Who this book is for....22
What this book covers....22
To get the most out of this book....24
Download the example code files....24
Conventions used....25
Get in touch....26
Free benefits with your book....28
How to unlock....29
Share your thoughts....29
1....31
Introducing TypeScript....31
Technical requirements....32
Why TypeScript?....33
Advantages of using TypeScript....33
Real-world applications of TypeScript....34
Getting started with TypeScript: installation and project setup....35
Understanding basic types in TypeScript....39
What are basic types in TypeScript?....39
How to use basic types in TypeScript....40
Arrays....42
Type inference....43
Working with complex types....44
Objects....44
Typesinterfaces....45
Tuples....46
Enums....47
Mastering advanced types....49
Union types: the power of OR....49
Intersection types: merging strengths....50
Generics: one tool, many types....51
Applications of generics....52
Generic classes: flexible object structures....54
Generic interfaces....55
Understanding conditional types in TypeScript....56
Configuring tsconfig.json....58
Diving into compilerOptions....58
Best practices for tsconfig.json maintenance....60
Summary....61
Get this book's PDF copy, code bundle, and more....62
2....63
Writing Clean Functions....63
Technical requirements....64
Learning principles of clean functions....64
Naming functions....65
Applying the Single Responsibility Principle....66
Understanding and avoiding (bad) side effects in TypeScript functions....69
Concurrency example....69
Parallelism example....70
Why this matters....70
How to avoid side effects....71
Understanding function signatures....71
Integrating TypeDoc for comprehensive TypeScript documentation....72
Creating static documentation pages with TypeDoc integration....81
Balancing comments and clean code....85
Summary....85
Get this book's PDF copy, code bundle, and more....86
3....87
Object-Oriented Programming with TypeScript....87
Technical requirements....88
What is object-oriented programming?....88
TypeScript objects....88
Object literals....89
Examplethe cake object....89
TypeScript classes....90
Static methods and properties in TypeScript....92
TypeScript classes: behind the scenes....94
Inheritance and prototype chains....96
Classical inheritance....96
Prototypal inheritance....97
Key differences....98
Understanding prototypes in TypeScript....98
Setting up the prototype chain....101
Using Object.create to set up the prototype chain....102
ES6 class inheritance with extends and super....102
Encapsulationprotecting your cake's recipe....104
Getters and setters: the gatekeepers of your data....105
Access modifiers: controlling access to your data....106
Polymorphism in TypeScript OOP....107
Method overriding....108
Interfaces....109
Interfaces versus classes: when to use each....109
Composition over inheritance for agile development....110
Summary....112
Get this book's PDF copy, code bundle, and more....113
4....115
Clean Code in TypeScript Projects....115
Technical requirements....116
Best practices for folder structure....116
Standard folder structure....116
Organizing by feature versus function....118
Feature-based organization....118
Function-based organization....118
Hybrid approach (common in practice)....119
Examples of both approaches....119
Learning module systems....121
What are module systems?....121
Defining a module....122
Encapsulation and scope management....122
Reusabilityimporting and using modules....123
Maintainability....124
Scalability....124
Improved testing....124
ES6 modules....125
CommonJS....126
Managing dependencies in TypeScript projects....127
Types of dependencies....128
Dependency managers in Node.js....128
Overview of npm, yarn, and pnpm....129
Checking for outdated dependencies....131
Updating dependencies....132
Linting and code formatting....134
Setting up ESLint....134
Step 1Install ESLint and required plugins....134
Step 2Initialize ESLint configuration....135
Step 3Test ESLint with a sample code file....136
Prettier setup and configuration....137
Summary....138
Get this book's PDF copy, code bundle, and more....139
5....141
Testing and Test-Driven Development....141
Technical requirements....141
Grasping the fundamentals of testing....142
Understanding levels of testing in software....143
Unit testing in TypeScript....143
Common terminology used in unit testtesting....144
Test case....144
Assertion....145
Mock....145
Approach 1: manual mocks (dependency injection)....146
Approach 2: mocking imported modules....147
Test runners....148
Choosing the right test runner....149
Setting up Vitest in a Node.js TypeScript project....149
Integration testing in TypeScript....155
What is integration testing?....155
Why integration testing?....155
Types of integration testing....156
Big bang approach....156
Incremental approach....156
Top-down approach....157
Bottom-up approach....157
Sandwichhybrid approach....158
Manual integration testing versus automated integration testing....159
Manual integration testing....159
Automated integration testing....160
Practical example of integration testing....162
Introducing TDD and its benefits....170
Best practices for TDD in TypeScript....170
Summary....174
Get this book's PDF copy, code bundle, and more....175
6....177
Error Handling, Debugging, and Security Best Practices....177
Technical requirements....178
Understanding error types and patterns....178
Introducing error types....178
Syntax errors....178
Type errors....181
Runtime errors....183
How to identify and resolve runtime errors....184
Logical errors....184
How to identify and resolve logical errors....185
Handling errors in TypeScript....187
Synchronous error handling....187
What are synchronous errors?....188
Fixing the issue with try...catch....190
Validating input data....192
Asynchronous error handling....194
What are asynchronous errors?....194
Strategies for handling asynchronous errors....195
Handling errors with promises....196
Handling errors with asyncawait....197
Best practices for robust asynchronous error handling....199
Debugging tools in TypeScript....200
Working with source maps....201
Using the VS Code debugger....202
Step 1: Create a launch configuration....203
Step 2: Add a breakpoint....205
Step 3: Start debugging....205
Leveraging console logs....208
Security best practices in TypeScript....210
Introduction to security practices....210
Input validation and data sanitization....211
Input validation....211
Data sanitization....212
Secure coding techniques....213
Error handling with security in mind....214
Managing sensitive data....215
Summary....217
Get this book's PDF copy, code bundle, and more....218
7....219
Maximizing Performance Optimization....219
Technical requirements....219
Understanding performance optimization....220
Why performance optimization matters....220
Common causes of poor performance in TypeScript applications....221
Code example: comparing iteration patterns....222
Performance versus readability....223
Key strategies for performance optimization....223
Why these strategies matter....224
Identifying performance bottlenecks....224
Using profiling tools to measure performance....224
Chrome DevTools Performance Profiler....224
Simple DEMO of Chrome DevTools Performance Profiler....225
Webpack Bundle Analyzer....228
Node.js performance hooks (for backend performance)....231
Detecting slow functions, excessive re-renders, and memory leaks....231
Example: Optimizing a slow function by avoiding repeated work....232
Detecting excessive re-renders in React....233
Detecting memory leaks....233
Strategies for prioritizing optimization efforts....236
Performance-enhancing techniques....236
Implementing lazy loading and code splitting....237
How to implement lazy loading in React....237
Code splitting: breaking large bundles into smaller chunks....238
Applying tree shaking to eliminate unused code....239
Optimized code with tree shaking....240
Leveraging caching mechanisms to improve speed....240
Common ways to apply caching....240
Optimizing loops, recursive functions, and asynchronous operations....241
Optimizing loops....241
Optimizing recursive functions....242
Choosing between loops and recursion....243
Optimizing asynchronous operations....244
Beyond debouncing....245
Summary....245
Get this book's PDF copy, code bundle, and more....246
8....247
Mastering Design Patterns in TypeScript....247
Technical requirements....248
Introducing design patterns....248
Creational patterns: Techniques for object creation....249
Factory method: Simplifying object creation....249
Abstract Factory: Creating related objects....251
Step 1: Define the product interfaces....251
Step 2: Create the concrete products for each theme....251
Step 3: Define the Abstract Factory interface....252
Step 4: Implement the concrete factories....252
Step 5: Use the factory (client code)....253
Builder: Constructing complex objects....253
Step 1: Define the complex object (the product)....254
Step 2: Create the Builder class....254
Step 3: Implement fluent methods....254
Step 4: Use the build method....255
Step 5: Use the builder (client code)....255
Builder pattern in modern TypeScript....255
Singleton: One instance only....256
Step 1: Use the private constructor....256
Step 2: Use the static accessor method....257
Step 3: Verifying the Singleton (client code)....257
Structural patterns: Techniques for class and object composition....258
Adapter: Making incompatible interfaces compatible....258
Step 1: The old system (the expectation)....259
Step 2: The new system (the incompatible class)....259
Step 3: The adapter (the bridge)....259
Step 4: Using the adapter....260
Composite: Treating individual objects and compositions uniformly....260
Step 1: Define the common interface (the component)....261
Step 2: Create the leaf nodes (individual objects)....261
Step 3: Create the Composite node (the container)....261
Step 4: Using the Composite structure....262
Decorator: Adding behavior without altering structure....262
Step 1: Define the base interface and component....263
Step 2: Create the decorators....263
Step 3: Stack the decorators (usage):....264
Facade: Simplifying complex subsystems....264
Step 1: The complex subsystems....265
Step 2: The facade (the remote control)....265
Step 3: Using the facade (client code)....266
Behavioral patterns: Defining object interaction and communication....267
Observer: Notifying dependent objects of changes in a subject....267
Step 1: Define the observer interface....267
Step 2: Implement the subject (the weather station)....268
Step 3: Create concrete observers....269
Step 4: Seeing it in action....269
Strategy: Allowing interchangeable algorithms in a single interface....270
Step 1: Define the Strategy interface....270
Step 2: Implement concrete strategies....270
Step 3: Create the context....271
Step 4: Switch strategies at runtime....271
Command: Encapsulating requests as objects to enable Undo and logging....272
Step 1: The receiver (the hardware)....272
Step 2: The Command interface....273
Step 3: Concrete commands (the cartridges)....273
Step 4: The invoker (the controller)....274
Step 5: Wiring it together (client code)....274
Iterator: Accessing elements in a collection without exposing its structure....275
Step 1: Define the Iterator interface....275
Step 2: Create the iterator logic....275
Step 3: Create the collection (the aggregate)....276
Step 4: Traversing the collection (client code)....276
Practical examples: Applying design patterns in real-world scenarios....277
Creational patterns....277
Example: Factory method in a notification system....277
Structural patterns: Adapter for third-party APIs....279
Behavioral patterns....280
Example: Observer in a real-time chat room....280
Example: Command for undo functionality in a text editor....281
When and where each pattern is most useful....283
Advantages and disadvantages of design patterns....284
Advantages of using design patterns....284
Disadvantages of using design patterns....285
When patterns might add complexity....285
Striking the right balance....286
Best practices for implementing design patterns in TypeScript....286
Summary....289
Get this book's PDF copy, code bundle, and more....289
9....291
Understanding Advanced TypeScript Features....291
Technical requirements....291
Exploring generics....292
Generics at work....292
Generic classes....292
Generic interfaces....293
Generic constraints....294
Advantages of generics....294
Introducing advanced types....295
Understanding decorators....299
How do decorators work?....299
Types of decorators....299
Benefits of decorators....301
Creating mapped types....302
How mapped types work....302
Examples of mapped types....303
Built-in mapped types....305
Advantages of mapped types....306
Best practices....306
Using conditional types....306
How conditional types work....307
Common use cases for conditional types....307
Combining conditional types with other features....309
Built-in conditional types....310
Best practices....310
Working with utility types....311
Key utility types in TypeScript....311
Best practices....316
Summary....317
Get this book's PDF copy, code bundle, and more....317
10....319
Setting Up Scalable TypeScript Projects....319
Technical requirements....320
From product spec to technical architecture....320
Understanding product specifications....321
From product spec to technical architecture....322
Breaking down the specification into a technical plan....322
Step 1Review and break down the specification....323
Functional requirements (DevJobs):....323
Non-functional requirements (DevJobs):....323
Step 2Add contextual constraints....323
Step 3Capture decisions before coding....324
Documenting architecture decisions with ADRs....325
Writing a simple ADR....325
Why this matters....326
Choosing a repository strategy for your project....326
Comparing monorepo and polyrepo approaches....327
Deciding between monorepo and polyrepo strategies....327
Choosing for DevJobs....328
Nxthe professional choice....328
Why Nx works well for TypeScript projects....329
Comparing Nx with alternatives....329
Setting up your Nx workspace....330
Workspace creation and configuration....330
Workspace structure and configuration....331
Generating and organizing your projects....332
Establishing the apps and libs convention....332
Installing required Nx plugins....333
Generating the frontend and backend applications....334
Generate the frontend (Next.js) application....334
Generate the backend (Express) application....336
Running the backend....337
Essential Nx commands and workflows....338
Code quality automation with Git hooks....339
Git hooks strategy....340
Husky and lint-staged setup....340
Step 1Install dependencies....341
Step 2Initialize Git....341
Step 3Initialize Husky....341
Step 4Add a pre-commit hook....342
Example commit flow....343
Testing the Git hook with a sample file....343
Step 1Create a test file....343
Step 2Stage the file....344
Step 3Commit the file....344
Step 4Verify the changes....345
Summary....346
Get this book's PDF copy, code bundle, and more....347
11....349
TypeScript in Action: Building Full Stack Applications....349
Technical requirements....349
Server-side TypeScript with Node.js....350
Implementing the contract-first approach....350
Step 1: Creating the openapi.yml file....351
Step 2: Defining the API specification....351
Step 3: Installing Orval and adding Orval config....353
Step 4: Generating the types....355
Adding feature modules....356
Tying it back to our product spec....357
Users module....358
Creating the first endpoint....359
Adding business logic to UserService....360
Step 1: Installing bcrypt for hashing passwords....360
Step 2: Basic in-memory registration with Orval types....361
Making a request to our newly created endpoint....362
Adding the findByEmail method to UsersService....363
Adding authentication to our backend....364
Step 1: Installing packages to help with authentication....364
Step 2: Scaffolding the Auth module, controller, and service....365
Step 3: Importing the relevant packages....365
Step 4: Configuring the Auth module....365
Production note: Symmetric versus asymmetric JWT signing....366
Step 5: Adding the authentication logic to the AuthService class....367
Step 6: AuthController – exposing authlogin....368
Step 7: Testing the authentication flow....369
Adding JWT guards to protect routes....371
Adding file-based persistence....372
Step 1: Creating a file storage utility....372
Step 2: Updating UsersService to persist data....373
Companies module....374
Step 1: Scaffolding the module....374
Step 2: Defining the service....374
Step 3: Defining the companies controller....375
Jobs module....376
Step 1: Service – jobs.service.ts....376
Step 2: Adding the jobs controller – jobs.controller.ts....378
Testing our devjobs backend full flow....378
Client-side TypeScript with React....380
Installing frontend dependencies....381
Creating the API client instance....381
Configuring Orval for frontend hooks....383
Setting up the React Query provider....385
Building the authentication flow....387
Creating the auth context....387
Login page....391
Step 1: Creating the login page and confirming that it renders....391
Step 2: Adding the login page to the router....392
Step 3: Adding a basic page shell (minimal styling with Tailwind)....392
Step 4: Adding the form and input fields (still no state)....393
Step 5: Tracking input values with state....394
Step 6: Handling form submission (still no API call)....395
Step 7: Calling the login API and storing the token....397
Step 8: Saving the token using AuthContext....397
Step 9: Displaying a friendly error message....398
Step 10: Disabling the login button while the request is in progress....399
Protected routes....401
Building the jobs page....402
Step 1: Starting with a simple jobs page shell....402
Step 2: Fetching jobs using useGetJobs....403
Step 3: Adding loading and error states....403
Step 4: Rendering the jobs list....403
Summary....404
Get this book's PDF copy, code bundle, and more....405
12....407
TypeScript in Evolving Systems....407
Technical requirements....408
Starting with a fast proof of concept....408
Detecting and handling contract drift....409
Making the contract explicit....410
The problem shared types don't solve by themselves....412
Protecting the JSON boundary with a runtime gate....412
Scaling the system without leaking vendor details....415
Making variants explicit with discriminated unions....416
Multiple endpoints without fragile casts....417
The payoff: moving failures earlier, on purpose....418
Summary....418
Get this book's PDF copy, code bundle, and more....419
13....421
Unlock Your Exclusive Benefits....421
Unlock this Book's Free Benefits in 3 Easy Steps....422
Step 1....422
Step 2....422
Step 3....423
Need Help....423
Why subscribe?....425
Other Books You May Enjoy....426
Packt is searching for authors like you....428
Share your thoughts....428
Index....429
Level up your TypeScript skills with practical techniques for writing robust, maintainable, and modern web applications
Clean Code with TypeScript is a practical guide to writing maintainable, efficient, and elegant TypeScript code. It equips developers with the essential principles and techniques to produce code that is both functional and easy to read and maintain.
Written by Rukevwe Ojigbo and Dr. Sanjay Krishna Anbalagan, expert software engineers with extensive experience in building scalable, high-performance applications across industries, this book reflects practical lessons from their real-world projects. Throughout the book, you’ll work through hands-on implementations, including an LLM integration project and a full-stack TypeScript application, ensuring the concepts are grounded, relevant, and applicable to real development environments.
What sets this book apart is its example-driven approach rooted in real-world scenarios. It goes beyond TypeScript best practices by developing your architectural thinking, enhancing team collaboration, and fostering long-term code quality. Whether you're new to TypeScript or an experienced developer, this guide will improve your TypeScript programming skills and help you deliver cleaner, more robust code.
*Email sign-up and proof of purchase required
The book is for JavaScript developers who want to master TypeScript to build scalable and maintainable applications. Frontend, backend, and full-stack developers, as well as software architects looking to leverage TypeScript for robust application design, will find practical value in this book. A basic understanding of JavaScript, including ES6+ features, functions, and asynchronous programming is assumed. Although not required, familiarity with TypeScript fundamentals, OOP principles, and Git is helpful.