Explore 1.5M+ audiobooks & ebooks free for days

From $11.99/month after trial. Cancel anytime.

Practical Advanced TypeScript
Practical Advanced TypeScript
Practical Advanced TypeScript
Ebook415 pages3 hoursEnglish

Practical Advanced TypeScript

Rating: 0 out of 5 stars

()

Read preview

About this ebook

Practical Advanced TypeScript is your one-stop guide to mastering TypeScript's advanced language features through a unique, hands-on approach. This book is perfect for developers looking to learn the language in depth, understand its latest features, and select the patterns that fit real-world projects perfectly.

 

Each topic in this book is explained in a well-defined and compact way, offering the fundamental specifics you need to be effective. With a step-by-step technique, you'll quickly get up and running with TypeScript, starting with realistic core concepts and building on them to help you grasp and utilize the more advanced language features. Important features receive in-depth treatment, and chapters address common issues while teaching you how to avoid them. This book is designed to be framework-agnostic, ensuring that the knowledge you gain can be applied to any project type and size , framework , library.

 

By the end of this TypeScript book, you'll be able to efficiently recognize when , why and how to apply appropriate techniques and advanced language features in any practical use case, and gain the confidence to work on scalable and maintainable TypeScript projects of any size.

 

Who this book is for

 

If you are already a JavaScript or TypeScript developer or at least you have experience using another programming language is required to get started

 

What you will learn

  1. Type System Multiverse & Type-level Programming with numerous hands-on examples in the context of a realistic scenarios

  2. Core and advanced TypeScript language features , with contextual explanations and code examples that help you grasp complex concepts with ease.
  3. Metaprogramming in Javascript with TypeScript
  4. AOP and OOP in TypeScript and separation of concerns into different entities
  5. (GoF) Design Patterns - Applying TypeScript and how Apply industry-standard design patterns to build modular code
  6. Explore and apply micro front-end technologies and techniques
  7. Asynchronous language features
  8. And much more
LanguageEnglish
PublisherBledar Ramo
Release dateApr 25, 2023
ISBN9798223047018
Practical Advanced TypeScript

Related authors

Related to Practical Advanced TypeScript

Related ebooks

Programming For You

View More

Related categories

Reviews for Practical Advanced TypeScript

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Practical Advanced TypeScript - Bledar Ramo

    Bledar Ramo

    Practical Advanced Typescript

    Hands-On Learning & Advanced concepts

    First published by Bledar Ramo 2023

    Copyright © 2023 by Bledar Ramo

    All rights reserved. No part of this publication may be reproduced, stored or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning, or otherwise without written permission from the publisher. It is illegal to copy this book, post it to a website, or distribute it by any other means without permission.

    Bledar Ramo asserts the moral right to be identified as the author of this work.

    Bledar Ramo has no responsibility for the persistence or accuracy of URLs for external or third-party Internet Websites referred to in this publication and does not guarantee that any content on such Websites is, or will remain, accurate or appropriate.

    Designations used by companies to distinguish their products are often claimed as trademarks. All brand names and product names used in this book and on its cover are trade names, service marks, trademarks and registered trademarks of their respective owners. The publishers and the book are not associated with any product or vendor mentioned in this book. None of the companies referenced within the book have endorsed the book.

    First edition

    This book was professionally typeset on Reedsy

    Find out more at reedsy.com

    In a world of ever-evolving complexity, TypeScript shines a light on the path to clarity and maintainability, guiding developers to create a brighter future in web development.

    Bledar Ramo

    Contents

    Preface

    Acknowledgement

    Intro

    1. Type System Multiverse & Type-level Programming

    2. Metaprogramming in Javascript with TypeScript

    3. Typescript Decorators

    4. Asynchronous language features

    5. Object Oriented Programming with TypeScript

    6. Functional Programming with TypeScript

    7. Aspect Oriented Programming inTypeScript

    8. Gangs of Four (GoF) Design Patterns - Applying TypeScript

    9. Microservice - Micro Frontend with TypeScript

    10. Compiler options

    11. Tooling & Ecosystem

    Conclusion

    Epilogue

    Afterword

    Code Samples

    About the Author

    Preface

    Since its release in 2012, TypeScript has experienced immense success, quickly establishing itself as a programming language within the JavaScript development community. With its strong typing and compile-time error checking, TypeScript offers a significant advantage to developers by promoting code quality and maintainability. Its inclusion in major projects, such as Angular 2.0, highlights the language’s value, flexibility, and the productivity enhancements achieved through its compiler and toolset.

    TypeScript’s compatibility with evolving ECMAScript standards allows developers to utilize language features before they become widely supported in browsers, ensuring applications stay ahead of the curve. Community has contributed an extensive collection of declaration files, which enable seamless integration with a wide array of JavaScript frameworks. These files enhance productivity, error detection, and IntelliSense features, providing a more robust development experience.

    Recognizing the growing number of TypeScript users, many JavaScript library developers now bundle TypeScript types in their releases to offer first-class support. This collaboration between library developers and community fosters a promotes and more efficient ecosystem. As TypeScript ultimately compiles down to JavaScript, it guarantees compatibility across all platforms that support JavaScript, making it a powerful and versatile choice for developers.

    In conclusion, TypeScript has emerged as a reliable tool for JavaScript developers, owing to its robust features, strong community support, and compatibility with existing JavaScript libraries and evolving standards. As a result ,has not only proven its worth but also become an essential part of modern web development.

    This book is designed for developers seeking to deepen their knowledge and expertise in TypeScript. It offers a comprehensive exploration of the advanced benefits and capabilities , providing in-depth guidance on how to control its full potential for complex projects. As such, it may not be suitable for beginners or junior developers seeking basic information . If you’re an experienced developer looking to take your TypeScript skills to the next level, then this book is the perfect resource for you.

    Acknowledgement

    I would like to thank my family, friends and colleagues for their support and encouragement during the writing of this book. I would also like to thank the TypeScript community for their valuable contributions and knowledge sharing that helped shape the content of this book . Finally, I would like to thank the readers who have embarked on this learning journey with me. Your dedication and curiosity is a constant inspiration.

    Intro

    Unlike many theory-heavy books, The Practical Advanced TypeScript balances clear explanations with hands-on practice. You’ll quickly be able to apply your new knowledge in the context of a realistic scenario, without having to wade through pages of history and monotonous, uninspiring content.

    This book dives deep into advanced concepts, techniques, and best practices, allowing developers to unlock TypeScript’s complete capabilities and develop stronger, more maintainable, and efficient codebases. With a strong focus on practical and real-world examples, and many hands-on exercises.

    No matter your choice of library or framework, the code examples and explanations in this book are not designed for a specific library or framework . Instead they provide an understanding that can be applied to any project where you’re using or considering TypeScript adoption. After finishing this book, you’ll be capable of taking on even the most difficult projects with confidence.

    1

    Type System Multiverse & Type-level Programming

    In this chapter, our goal is to explore and learn in depth TypeScript’s Type System and Type-level programming . We will begin with concepts such as union types, intersection types, generics, constraints, type aliases, mapped types, guards, type inference and many more. We’ll also learn how to effectively combine these and many other types in practical situations using various built-in TypeScript operators and utilities. For each concept, I will provide in-depth content and plenty of examples. This will give you a solid understanding of the type system and guide you through its most advanced features. A brief explanation of all the operators and utilities featured in the examples throughout this chapter can be found in the concluding section.

    Conditional Types

    type IsArray = T extends any[] ? true : false;

    type ArrayOrNot = IsArray extends true ? T : T[];

     

    const arr1: number[] = [1, 2, 3];

    const arr2: string[] = [a, b, c];

    const num: number = 42;

     

    const arrOrNot1: ArrayOrNot = arr1; // Type is number[]

    const arrOrNot2: ArrayOrNot = arr2; // Type is string[]

    const arrOrNot3: ArrayOrNot = num; // Type is number

    To validate if a type is an array or not, we define two advanced type features in this example called IsArray and ArrayOrNot that use conditional types. IsArray evaluates a type’s extends clause and returns a boolean answer. With the aid of IsArray, ArrayOrNot can conditionally return either the original type or an array of the original type.

    Based on that, three variables with distinct types are defined: arr1, arr2, and num. Finally, we define three variables with ArrayOrNot-inferred types: arrOrNot1, arrOrNot2, and arrOrNot3. While arrOrNot3 is inferred to be a simple number, arrOrNot1 and arrOrNot2 are inferred to be arrays of their respective types.

    Advance example of using conditional types from a real-world scenario

    interface User {

    d: number;

      name: string;

      email: string;

      address: string;

    }

     

    interface Admin {

      id: number;

      name: string;

      email: string;

      role: string;

    }

     

    interface SuperAdmin {

      id: number;

      name: string;

      email: string;

      role: string;

      permissions: string[];

    }

     

    type RoleType = T extends { role: string } ? T : User;

     

    type AdminOrSuperAdmin = T extends { role: 'admin' } ? Admin : T extends { role: 'superadmin' } ? SuperAdmin : T;

     

    function getUser(data: T): AdminOrSuperAdmin> {

      if (data.role) {

        if (data.role === 'admin') {

          return { id: 1, name: data.name, email: data.email, role: data.role } as AdminOrSuperAdmin>;

        } else if (data.role === 'superadmin') {

          return { id: 1, name: data.name, email: data.email, role: data.role, permissions: [] } as AdminOrSuperAdmin>;

        }

      }

     

      return { id: 1, name: data.name, email: data.email, address: data.address } as AdminOrSuperAdmin>;

    }

     

    const user = getUser({ id: 1, name: 'John', email: 'john@example.com', address: '123 Main St' });

    const admin = getUser({ id: 2, name: 'Jane', email: 'jane@example.com', role: 'admin' });

    const superadmin = getUser({ id: 3, name: 'Bob', email: 'bob@example.com', role: 'superadmin' });

     

    console.log(user); // Output: { id: 1, name: 'John', email: 'john@example.com' }

    console.log(admin); // Output: { id: 2, name: 'Jane', email: 'jane@example.com', role: 'admin' }

    console.log(superadmin); // Output: { id: 3, name: 'Bob', email: 'bob@example.com', role: 'superadmin', permissions: [] }

    This time we created three interfaces—User, Admin, and SuperAdmin—that describe various user types and their corresponding levels of access.

    The RoleType type evaluates a type T to see if it extends an object with a role property. If it does, the type is assumed to be the user type; otherwise, it is assumed to be the object with the role property.

    This type check whether a type T extends an object with an admin role property. If so, the type is inferred to be admin; otherwise, it determines whether the object has a superadmin role property. If this is the case, the type will be SuperAdmin; otherwise, it will be T. With this type, we can create functions that, depending on the input data, return a variety of types.

    GetUser is a function that accepts a generic type T that extends an object with a role property. Based on the implied AdminOrSuperAdmin> type, the function decide whether the role property is present and returns the appropriate user type.

    Mapped Types

    Mapped types are a powerful feature that allows you to create new types by transforming the properties of existing ones, often making it easier to keep your types DRY (Don’t Repeat Yourself) and maintainable.

    type Point = { x: number; y: number };

    type PointMap = { [K in keyof T]: T[K] };

     

    const point: Point = { x: 10, y: 20 };

    const : PointMap = { x: 10, y: 20 };

     

    function getPoint(key: K): Point[K] {

      return point[key];

    }

     

    console.log(getPoint(x)); // Outputs: 10

    console.log(getPoint(y)); // Outputs: 20

    In this example, we define a type called Point with two properties, x and y, each with a type of number. We then define a type called PointMap that uses a mapped type to create a new type with the same properties as T, but with the same value types. We then define a variable point of type Point, and a variable pointMap of type PointMap. pointMap has the same properties as point, but with no additional properties. We then define a function getPoint that takes a parameter key of type K, which must be a key of the Point type.

    The function returns the value of the property specified by key on the point object. Finally, we log the results of calling getPoint with the keys x and y, which output 10 and 20 respectively. This is an example of mapped types in TypeScript that allow you to create new types based on existing ones with ease.

    Here’s an example of using a mapped type to transform an object type

    interface Person {

      name: string;

      age: number;

    }

     

    type Optional = {

      [K in keyof T]?: T[K];

    }

     

    type OptionalPerson = Optional;

     

    const person: OptionalPerson = { name: 'John' };

    In this example, we define an interface Person with two properties, name and age. We then define a type Optional that takes a type T and creates a new type that has all of the properties of T, but each property is optional

    We define a new type OptionalPerson that is the result of applying the Optional transformation to the Person type. This creates a new type that has all of the properties of Person, but each property is optional

    We create a new variable person that is of type OptionalPerson. We can see that the age property is not required, as it is marked as optional in the OptionalPerson type.

    Tuple Type

    In my opinion one of the most powerful feature that allows you to create new types by transforming properties of existing types, enabling operations like making all properties optional, read-only, or applying other transformations in a concise and reusable manner.

    type Person = { name: string, age: number };

    type ReadOnlyPerson = {

      readonly [K in keyof Person]: Person[K]

    };

     

    const person: ReadOnlyPerson = { name: John, age: 30 };

    person.name = Jane; // error: Cannot assign to 'name' because it is a read-only property.

    In this example, we’re using a mapped type to create a ReadOnlyPerson type that makes all properties of Person readonly. This allows us to enforce immutability for certain types in our code.

    Here’s a simple example

    const user: [number, string, boolean] = [1, 'Alice', true];

    In this code snippet, user is defined as a tuple with three elements: a number, a string, and a boolean.

    Another example of a tuple

    type RGBColor = [number, number, number];

     

    const convertToRGB = (hex: string): RGBColor => {

      // Conversion logic

      // ...

      return [255, 255, 255]; // Example output: white color as RGB

    };

     

    const whiteColor: RGBColor = convertToRGB('#FFFFFF');

    In this code snippet, we define a RGBColor tuple type representing an RGB color with three elements, each being a number. The convertToRGB function takes a hex color string and returns its equivalent RGB color as a RGBColor tuple.

    Here’s an example of using a mapped type to transform a tuple type

    type TupleToUnion = T[number];

     

    type Colors = ['red', 'green', 'blue'];

    type ColorUnion = TupleToUnion;

     

    const color: ColorUnion = 'red';

    In this example, we define a type called TupleToUnion that takes a tuple of type T and produces a new type that is the union of all the tuple’s elements. To do this, we use the number index signature to get the total of each tuple element. We introduce the new type Colors, a tuple type with three string elements. After applying the TupleToUnion transformation to the Colors type, we define a new ColorUnion type.

    As a result, a brand-new type that represents the collection of the Colors tuple’s components is produced. We make a new color variable of type ColorUnion. We can see that it is the total of all the string components in the Colors tuple. In this example, we will swap the types of an object and a tuple using TypeScript’s mapped types.

    Advance example of using mapped types in TypeScript

    interface User {

      name: string;

      age: number;

      address: {

        street: string;

        city: string;

        state: string;

        zip: string;

      };

    }

     

    type Optional = { [K in keyof T]?: T[K] };

     

    type Nullable = { [K in keyof T]: T[K] | null };

     

    type Readonly = { readonly [K in keyof T]: T[K] };

     

    type PartialWithKeysMatching = Omit & Partial>>;

     

    type KeysMatching = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];

     

    type UserOptional = Optional;

    type UserNullable = Nullable;

    type UserReadonly = Readonly;

    type UserPartialAddress = PartialWithKeysMatching;

     

    const user: User = {

      name: 'John',

      age: 30,

      address: {

        street: '123 Main St',

        city: 'Anytown',

        state: 'CA',

        zip: '12345'

      }

    };

     

    const userOptional: UserOptional = {

      name: 'John',

      age: 30,

      address: {

        street: '123 Main St',

        city: 'Anytown',

        state: 'CA',

        zip: '12345'

      }

    };

     

    const userNullable: UserNullable = {

      name: 'John',

      age: null,

      address: {

        street: '123 Main St',

        city: 'Anytown',

        state: 'CA',

        zip: '12345'

      }

    };

     

    const userReadonly: UserReadonly = {

      name: 'John',

      age: 30,

      address: {

        street: '123 Main St',

        city: 'Anytown',

        state: 'CA',

        zip: '12345'

      }

    };

     

    const userPartialAddress: UserPartialAddress = {

      name: 'John',

      age: 30,

      address: {

        zip: '67890'

     

    Enjoying the preview?
    Page 1 of 1