Category: 06. Advanced Types

https://cdn3d.iconscout.com/3d/premium/thumb/advanced-search-3d-icon-png-download-7946846.png

  • Type Assertions

    Type assertion is a mechanism in TypeScript that informs the compiler of the variable type. We can override the type using a type assertion if TypeScript finds that the assignment is wrong. We must be certain that we are correct since the assignment is always legitimate when we employ a type assertion. If not, our program might not operate properly.

    Type assertion functions similarly to typecasting, but unlike C# and Java, it does not do type verification or data rearrangement. Runtime support is provided for typecasting, although type assertion does not affect runtime. Type assertions are solely a compile-time construct to give the compiler indications about how we want our code to be inspected.

    How to Perform Type Assertions?

    Type assertion is a Typescript technique that tells the compiler about the type of variable. Though type assertion doesnt recreate code, typecasting does. You can tell the compiler not to infer the type of a value by using type assertion. We utilize Type assertion to convert a variable from one type to another, such as any to a number. To do type assertion, we can either use the “<>” operator or the “as” operator. Typecasting provides runtime support, whereas type assertion has no impact on runtime. There are three techniques to perform Type Assertion in TypeScript, and those are:

    • Using as operator
    • Using <> operator
    • Using object

    Using as Operator for Type Assertion

    The as keyword in TypeScript offers a method for displaying Type Assertion.

    Syntax

    let variable_any:any=123let variable_number:number= variable_any asnumber

    In the above syntax, we used the “as” keyword on any type variable for type assertion.

    Example

    let variable_unknown:unknown="Tutorialspoint";console.log("variable_unknown value is: ", variable_unknown);let variable_number:number=(variable_unknown asstring).length;console.log("Length of variable_unknown: ", variable_number);

    On compiling, it will generate the following JavaScript code:

    var variable_unknown ="Tutorialspoint";console.log("variable_unknown value is: ", variable_unknown);var variable_number = variable_unknown.length;console.log("Length of variable_unknown: ", variable_number);

    The output will be:

    variable_unknown value is: Tutorialspoint
    Length of variable_unknown: 14
    

    Using <> Operator for Type Assertion

    The <> operator is another way to perform type assertion in TypeScript.

    Syntax

    let variable_any:any=123let variable_number:number=<number> variable_any
    

    In the above syntax, we used the “<>” operator on any type variable for type assertion.

    Example

    let my_number:unknown=12345console.log('my_number value is: ', my_number)let num:number=<number>my_number
    console.log('typeof num is: ',typeof num)

    On compiling, it will generate the following JavaScript code:

    var my_number =12345;console.log('my_number value is: ', my_number);var num = my_number;console.log('typeof num is: ',typeof num);

    The output will be:

    my_number value is: 12345
    typeof num is: number
    

    Using Object for Type Assertion

    Objects are another way to perform the type assertion, unlike the “as” and “<>” operators; the objects can use for multiple type assertions at once.

    Syntax

    interfaceinfo{
       name:string,
       value:string}let my_obj =<info>{ name:'ABC', value:'abc'}

    In the above syntax, we used the object to perform type assertion.

    Example

    interfaceinfo{
       name:string
       value:string}let my_obj =<info>{}
    my_obj.name ='Tutorialspoint'
    my_obj.value ='typescript'console.log(my_obj)

    On compiling, it will generate the following JavaScript code:

    var my_obj ={};
    my_obj.name ='Tutorialspoint';
    my_obj.value ='typescript';console.log(my_obj);

    The output will be:

    { name: 'Tutorialspoint', value: 'typescript' }
  • Type Guards

    In TypeScript, the type guards are used to determine a variable’s type, often inside a conditional or functional block. The type guards usually take the variable and return a Boolean value or the variable type. Type guards allow you to tell the TypeScript compiler to infer a given type for a variable in a specific context, guaranteeing that an argument’s type is what you say it is.

    Similar to feature detection, type guards are commonly used to narrow down a type, enabling you to identify the appropriate prototypes, methods, and attributes of a value. As a result, handling that value become simple for the user.

    The user-defined type guards can be created in TypeScript, but it also has built-in operators like the ‘typeof’, ‘in’, and the ‘instanceof’ operator.

    The ‘typeof’ type guard in TypeScript

    In TypeScript, the ‘typeof’ operator is used to get the type of the variable. According to the variable’s type, it returns the values like

    • Number
    • String
    • Boolean
    • Object
    • Bigint
    • Symbol
    • Function
    • Undefined

    Syntax

    Users can follow the below syntax to use the ‘typeof’ type, guard operator.

    typeof variable_name
    

    In the above syntax, we use the typeof operator just before the variable name to get the variable type.

    Example

    In the following example, we will use the ‘typeof’ type guard in TypeScript. We have declared four variables of types’ number’, ‘string’, ‘boolean’, and ‘object’. After that, we console log their variable type using the ‘typeof’ operator of the TypeScript.

    let my_number:number=123let my_string:string='Tutorialspoint'let my_boolean:boolean=truelet my_object:{ id:number}={ id:1}console.log('type of my_number variable is: '+typeof my_number)console.log('type of my_string variable is: '+typeof my_string)console.log('type of my_boolean variable is: '+typeof my_boolean)console.log('type of my_object variable is: '+typeof my_object)

    On compiling, it will generate the following JavaScript code

    var my_number =123;var my_string ='Tutorialspoint';var my_boolean =true;var my_object ={ id:1};
    console.log('type of my_number variable is: '+typeof my_number);
    console.log('type of my_string variable is: '+typeof my_string);
    console.log('type of my_boolean variable is: '+typeof my_boolean);
    console.log('type of my_object variable is: '+typeof my_object);

    Output

    The above code will produce the following output

    type of my_number variable is: number
    type of my_string variable is: string
    type of my_boolean variable is: boolean
    type of my_object variable is: object
    

    In the above output, users can see the output of the ‘typeof’ operator for four variables: ‘number’, ‘string’, ‘boolean’, and ‘object’.

    The ‘in’ type guard in TypeScript

    The ‘in’ type guard determines if an object contains a specific attribute, which is then used to distinguish between distinct types. It typically returns a boolean, indicating if the property is present in the object. It is utilized for its narrowing characteristics.

    Syntax

    Users can follow the below syntax to use the ‘in’ type guard operator.

    property_name in object_name
    

    In the above syntax, we use the ‘in’ operator to find whether the property exists in the object.

    Example

    In the following example, we will use the ‘in’ type guard in TypeScript. We have declared three objects that consist of different properties. We use the’ in’ type guard to check whether a required property exists in the object. We can even check if a property contains another property or if it is not using it. In the ‘obj3’, we check if an object’s property contains another property or not.

    let obj1:{ id:number; name:string}={ id:1, name:'Tutorialspoint'}let obj2:{ name:string; roll:number}={ name:'XYZ', roll:12}let obj3:{ id:number; marks:{ english:number; math:number}}={
       id:101,
       marks:{
    
      math:90,
      english:80,},}console.log('Is name in obj1? =&gt; '+('name'in obj1))console.log('Is id obj2? =&gt; '+('id'in obj2))console.log('Is marks in obj3? =&gt; '+('marks'in obj3))console.log('Is math in obj3.marks? =&gt; '+('math'in obj3.marks))</code></pre>

    On compiling, it will generate the following JavaScript code

    var obj1 ={ id:1, name:'Tutorialspoint'};var obj2 ={ name:'XYZ', roll:12};var obj3 ={
       id:101,
       marks:{
    
      math:90,
      english:80}};
    console.log('Is name in obj1? => '+('name'in obj1)); console.log('Is id in obj2? => '+('id'in obj2)); console.log('Is marks in obj3? => '+('marks'in obj3)); console.log('Is math in obj3.marks? => '+('math'in obj3.marks));

    Output

    The above code will produce the following output

    Is name in obj1? => true
    Is id in obj2? => false
    Is marks in obj3? => true
    Is math in obj3.marks? => true
    

    In the above output, users can see the output of the 'in' operator in different circumstances in our code.

    The 'instanceof' type guard in TypeScript

    The 'instanceof' is a built-in type guard used to determine whether a value is an instance of a specific constructor function or class. We may use this type-guard to determine the type of instance type by testing if an object or value is derived from a class.

    Syntax

    Users can follow the below syntax to use the 'instanceof' type-guard operator.

    object_name instanceof class_name
    

    In the above syntax, we use the 'instanceof' operator to find whether the object is an instance of the class.

    Example

    In the following example, we will use the 'instanceof' type guard in TypeScript. We have declared a 'Parent' class and a child classe, 'Child'. We declare an objects of the 'Child' class and use the 'instanceof' operator to find the object belongs to which class.

    classParent{
       id:numberconstructor(id:number){this.id = id
       }}classChildextendsParent{
       id:number
       name:stringconstructor(id:number, name:string){super(id)this.name = name
       }}let child =newChild(101,'ABC')console.log('child instanceof Child => '+(child instanceofChild))console.log('child instanceof Parent => '+(child instanceofParent))

    On compiling, it will generate the following JavaScript code

    var __extends =(this&&this.__extends)||(function(){varextendStatics=function(d, b){
    
      extendStatics = Object.setPrototypeOf ||({ __proto__:&#91;]}instanceofArray&amp;&amp;function(d, b){ d.__proto__ = b;})||function(d, b){for(var p in b)if(b.hasOwnProperty(p)) d&#91;p]= b&#91;p];};returnextendStatics(d, b);};returnfunction(d, b){extendStatics(d, b);function__(){this.constructor = d;}
      d.prototype = b ===null? Object.create(b):(__.prototype = b.prototype,new__());};})();var Parent =/** @class */(function(){functionParent(id){this.id = id;}return Parent;}());var Child =/** @class */(function(_super){__extends(Child, _super);functionChild(id, name){var _this =_super.call(this, id)||this;
      _this.name = name;return _this;}return Child;}(Parent));var child =newChild(101,'ABC');
    console.log('child instanceof Child => '+(child instanceofChild)); console.log('child instanceof Parent => '+(child instanceofParent));

    Output

    The above code will produce the following output

    child instanceof Child => true
    child instanceof Parent => true
    

    In the above output, users can see the output of the 'instanceof' operator when used in different classes and their objects.

  • Intersection Types

    In TypeScript, an intersection type combines multiple types into one. Although intersection and union types in TypeScript are similar, they are used in very different ways. A type that combines different types into one is called an intersection type. This enables you to combine many types to produce a single type with all the necessary attributes. Members from each of the provided types will be present in an object of this type. The intersection type is made using the ‘&’ operator.

    When two types intersect in TypeScript, the intersection type will inherit the characteristics of both intersecting types. Take caution when combining types that share property names with different kinds.

    Syntax

    We can write the below syntax to create an Intersection type in TypeScript.

    typeintersepted_Type= Type1 & Type2;

    Example

    In the example below, we have created two interfaces named “Book” and “Author”. Now inside the Book, we have created two fields named “book_id”, which is of number type, and “book_name”, which is of string type. And inside the Author, we have also created two fields named “author_id”, which is of number type, and “author_name”, which is of string type. Next, we intersected the Book and Author interface and stored it into intersected_types. Finally, values are retrieved from an object of the intersection type created.

    interfaceBook{
       book_id:number
       book_name:string}interfaceAuthor{
       author_id:number
       author_name:string}typeintersected_type= Book & Author
    let intersected_type_object1: intersected_type ={
       book_id:101,
       book_name:'Typescript is Awesome',
       author_id:202,
       author_name:'Tutorialspoint!',}console.log('Book Id: '+ intersected_type_object1.book_id)console.log('Book name: '+ intersected_type_object1.book_name)console.log('Author Id: '+ intersected_type_object1.author_id)console.log('Author name: '+ intersected_type_object1.author_name)

    On compiling, it will generate the following JavaScript code

    var intersected_type_object1 ={
       book_id:101,
       book_name:'Typescript is Awesome',
       author_id:202,
       author_name:'Tutorialspoint!'};
    console.log('Book Id: '+ intersected_type_object1.book_id);
    console.log('Book name: '+ intersected_type_object1.book_name);
    console.log('Author Id: '+ intersected_type_object1.author_id);
    console.log('Author name: '+ intersected_type_object1.author_name);

    Output

    The above code will produce the following output

    Book Id: 101
    Book name: Typescript is Awesome
    Author Id: 202
    Author name: Tutorialspoint!
    

    As users can see in the output, all the values of two different interfaces are combined and displayed.

    Intersection types are Associative and Commutative

    The commutative property indicates that an equation’s factors can be freely rearranged without altering the equation’s outcome.

    commutative property:  (A & B) = (B & A)

    Associative property asserts that altering how integers are grouped during an operation will not affect the equation’s solution.

    associative property: (A & B) & C = A & (B & C)

    When we cross two or more kinds, it doesn’t matter what order they are in. The ‘typeof’ operator is used to verify that the attributes of the intersected objects are also the same, regardless of how the items are intersected or in what order.

    Example

    As we can see in the below example, here we have created three interfaces named “Student”, “Class”, and “Subject”. Now inside the Student, we have created two fields called “student_id”, which is of number type, and “sudent_name”, which is of string type. Inside the “Class” instance, we have also created two fields named “class_id”, which is of number type, and “class_name”, which is of string type. Inside the “Subject” instance, we have also created two fields named “subject_id”, which is of number type, and “subject_name”, which is of string type.

    Next, we intersected the Book, Author, and Subject interface using associative property and stored it into intersected types. After that, values are retrieved from an object of the intersection type created. Finally, we checked the objects using the typeof operator and logged in to the console.

    interfaceStudent{
       student_id:number
       student_name:string}interfaceClass{
       class_id:number
       class_name:string}interfaceSubject{
       subject_id:number
       subject_name:string}typeintersected_type_1=(Student & Class)& Subject
    typeintersected_type_2= Student &(Class & Subject)let intersected_type_object1: intersected_type_1 ={
       student_id:101,
       student_name:'Typescript',
       class_id:10,}let intersected_type_object2: intersected_type_2 ={
       student_id:102,
       student_name:'Typescript2',
       class_id:11,}console.log(typeof intersected_type_object1 ===typeof intersected_type_object2)

    On compiling, it will generate the following JavaScript code

    var intersected_type_object1 ={
       student_id:101,
       student_name:'Typescript',
       class_id:10};var intersected_type_object2 ={
       student_id:102,
       student_name:'Typescript2',
       class_id:11};
    console.log(typeof intersected_type_object1 ===typeof intersected_type_object2);

    Output

    The above code will produce the following output

    true
    

    As users can see in the output, both the attributes of the objects are identical, showing the true value.