Mastering TypeScript: Unveiling Types and Techniques

Mastering TypeScript: Unveiling Types and Techniques

Hey TECHIE curious about TypeScript's ?

Let's explore the world of types together, unraveling their importance and how they make your code stronger.

There are various types available in Typescript

String

  • It represents the string value like "Hello World"

  •   const welcomeMessage: string = "Hello World";
    
  • The beauty of TypeScript is that when you use the variable welcomeMessage it provides only those methods that are available in String, other methods are automatically get narrow down

Number

  • It Represents Numbers like 42, 10, 52.33

  • There are NO Integer or Float values, They are just Numbers

  •   const userId: number = 123;
    

Boolean

  • It Represents True / False

  •    const isLoggedIn: boolean = false;
    

Array

  • There are multiple ways to define an Array

  •   const users: string[] = [];
      // Array of Strings
    
      const userIds: number[] = [];
      // Array of Numbers
    
      const usersInfo:Array<number> = [];
      // Arrays of Numbers
    

Any

  • Any is a kind of getaway, where you do not let the type/ static checking

  • Any should be avoided in most of the cases

  • Any simply means turn off the checking for this particular instance

  • It is like you are making your code more JavaScript manner

  •   let myName;
      function printName() {
        return true; 
        // We can return string, number, anything (NO ONE IS STOPPING US)
      }
      myName = printName();
      // myName is of Type any
      // PrintName function can return anything to us....
      // It could be string, number, etc
    
  • Interestingly, Typescript offers a method that prevents us from using any

  • Method is noImplicitAny

  • In the TS config file, we can add a flag noImplicitAny

  • Use the compiler flag noImplicitAny to flag any as an error

Functions

  • Functions are the heart and soul of Programming

  • In most cases, types are inferred from the parent, but not in the case of Functions

  • Apart from function, Typescript is smart info to infer the type

  • In Functions, typescript can't infer the type

  •   // WHEN WE ARE NOT USING TYPE
      EXAMPLE - 1
      function addNumber(value) {
        return value + 5;
        return "abc"
        return false
      // We can return a string, a number, a boolean, Therefore perfroming any operation based on the return is not possible
      }
    
      addNumber("Ankush");
      addNumber(true)
      // We can Pass anthing in the Parameters, NO ONE IS STOPPING US
      // This is very bad when it comes to big end application
    
      EXAMPLE-2
      function upperCase(value){
      return value.toUpperCase() /* STRING method */
      return value.toFixed() /* NUMBER method */
      }
      upperCase(30);
      upperCase(true);
      // Here we are using String & Number Methods on the same value which will definitely cause an break in the application
    
  • Suppose You've got a function that's the backbone of your code. Everything depends on its result. But if someone changes its return type by mistake, your whole program breaks down

  • To address this issue, we utilize TypeScript.

  • By doing so, the next developer who works on the code understands that this particular function is expected to return a numerical value.

  •    // WHEN WE ARE USING TYPESCRIPT
      EXAMPLE - 1
      function addNumber(value:number): number {
      return value + 5;
      }
      addNumer(10)
      // Here value should be number and Type should also be number
      // MUCH BETTER code as compared to previous one, We know the parameter and return Type
    
      EXAMPLE-2
      function upperCase(value: string) : string {
      // We can also access those function that are present in the String 
      return value.toUpperCase()
       }
      upperCase("ankush")
    
      // FUNCTION WHICH RETURN PROMISE
      async function getFavoriteNumber(): Promise<number> {
       return 26;
      }
    

Objects

    // creating a type of CreditCard
    type creditCard = {
      last4: number;
      expiryDate: string;
      cvv: number;
      isPremiumMember: boolean;
    };

    // creating a type of user
    type User = {
      readonly _id: string; /* You cannot Change Read Only */
      name: string;
      email: string;
      isActive: boolean;
      creditCardDeatils?: creditCard; /* ? stands for => for Optional */
      entireCardDetails?: entireCardDetails;
    };
    // Optional Parameters are not Mandatory

    // Implementing the user type
    let NewUser: User = {
      _id: "123",
      name: "ankush",
      email: "ankush@ankush.com",
      isActive: true,
    };

    NewUser.email = "ankush@gmail.com";
    // NewUser._id = "56565"; we cannot change the ID
  • Learnings:

    • We can create type using the keyword type

    • readonly_id => User is not allowed to change the value

    • ? stands for Optional Parameter

    • Optional Parameters are not mandatory

    • when you read from an optional property, you’ll have to check for undefined before using it, because if you access a property that doesn’t exist you’ll get the value undefined rather than a runtime error.

    •       function printName(obj: { first: string; last?: string }) {
              // Error - might crash if 'obj.last' wasn't provided!
              console.log(obj.last.toUpperCase());
            'obj.last' is possibly 'undefined'.
              if (obj.last !== undefined) {
                // OK
                console.log(obj.last.toUpperCase());
              }
      
              // A safe alternative using modern JavaScript syntax:
              console.log(obj.last?.toUpperCase());
            }
      

Union

  • It is a way of combining types

  • A union type is a type formed from two or more other types

  • Union represents with Pipe Symbol ->|

  •    function printId(id: number | string) {
            console.log("Your ID is: " + id);
          }
          // OK
          printId(101);
          // OK
          printId("202");
          // Error
          printId({ myID: 22342 });
          Argument of type '{ myID: number; }' is not assignable to parameter of type 'string | number'.
    
  • Most Important point

  • TypeScript will only allow an operation if it is valid for every member of the union

  • For example, if you have the union string | number, you can’t use methods that are only available on string:

  •     function printId(id: number | string) {
          console.log(id.toUpperCase());
    
          Property 'toUpperCase' does not exist on type 'string | number'.
          Property 'toUpperCase' does not exist on type 'number'.
        }
    
  • The solution is to narrow the union with code, the same as you would in JavaScript without type annotations.

  •    function printId(id: number | string) {
          if (typeof id === "string") {
            // In this branch, id is of type 'string'
            console.log(id.toUpperCase());
          } else {
            // Here, id is of type 'number'
            console.log(id);
          }
        }
        // YOU NEED TO CHECK THE TYPE, because at the top you have specified the type as Union
    

Type Assertions

  • Sometimes you will have a value that TypeScript can’t know about.

  • For example, if you’re using document.getElementById, TypeScript only knows that this will return some kind of HTMLElement, but you know that your page will always have an HTMLCanvasElement with a given ID.

  • then we can use type assertion to specify a more specific type:

  •   const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
    
        // Another way
        const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
    
  • Like a type annotation, type assertions are removed by the compiler and won’t affect the runtime behavior of your code. You can also use the angle-bracket syntax

Literal Types

  • In addition to the general types string and number, we can refer to specific strings and numbers in type positions.

  •   let x: "hello" = "hello";
        // OK
        x = "hello";
        // ...
        x = "howdy";
        Type '"howdy"' is not assignable to type '"hello"'.
    
  • It’s not much use to have a variable that can only have one value!

  • But by combining literals into unions, you can express a much more useful concept - for example, functions that only accept a certain set of known values

  •    function printText(s: string, alignment: "left" | "right" | "center") {
          // ...
        }
        printText("Hello, world", "left");
        printText("G'day, mate", "centre");
        Argument of type '"centre"' is not assignable to parameter of type '"left" | "right" | "center"'.
    

Thank you for your valuable time. I hope this article is helpful in some way. Please feel free to leave your valuable comments.

Did you find this article valuable?

Support Ankush Thakur by becoming a sponsor. Any amount is appreciated!