TypeScript – Type Compatibility ”; Previous Next In TypeScript, type compatibility refers to the ability to assign one type of variable, object, etc. to another type. In other words, it refers to the ability to check whether two types are compatible with each other based on the structure of them. For example, string and boolean types are not compatible with each other as shown in the code. let s:string = “Hello”; let b:boolean = true; s = b; // Error: Type ”boolean” is not assignable to type ”string” b = s; // Error: Type ”string” is not assignable to type ”boolean” TypeScript”s type system allows to perform certain operations that are not safe at compile time. For example, any types of variable are compatible with ”any”, which is unsound behavior. For example, let s: any = 123; s = “Hello”; // Valid How TypeScript Performs Type Compatibility Checks? Typescript uses the structural subtyping and structural assignment for performing the type compatibility checks. Let”s learn each with examples. Structural Subtyping TypeScript uses the structural subtyping method to check whether the particular type is the subtype of another type. Even if the name of the members of a particular type doesn”t match but the structure matches, the TypeScript compiler considers both types the same. For example, interface Person { name: string; } let person: Person; let obj = { name: “John”, age: 30 }; // Ok person = obj; To check whether the type of the ”obj” object is compatible with the type of the Person interface, typescript checks if ”obj” contains at least all properties and methods included in the Person interface. TypeScript doesn”t care about the extra members added to the subtype. Here, the obj object contains an extra ”age” property but still, it is compatible with the Person type as the obj object contains the ”name” property of the string type. If the ”obj” object doesn”t contain all members of the Person interface, it is not assignable to the object with Person type. For example, interface Person { name: string; } let person: Person; let obj = { n: “John”, age: 30 }; // Not Ok person = obj; The above code throws an error when we compile it as a type of ”obj” object that is not the same as the Person interface. How to Use Type Compatibility Effectively? Developers can use the interface and generics to use the types effectively in TypeScript. Here are the best tips for using the interface and generics for type compatibility. Using Interfaces Using an interface developer can define contracts or types to ensure that implementation adheres to these types. It is useful in ensuring the type compatibility across different parts of your code. Let”s understand it via the example below. Example In the example below, the ”user2” variable has the type ”User”. So, developers can assign objects having the same properties as the ”User” interface to the ”user2” object. interface User { name: string; age: number; } const user = { name: “Alice”, age: 30 }; let user2: User = user; console.log(user2) On compiling, it will generate the following JavaScript code. const user = { name: “Alice”, age: 30 }; let user2 = user; console.log(user2); Output Its output is as follows – { name: ”Alice”, age: 30 } Using Generics We can use generics to create reusable components that can work with multiple data types instead of single data types. It allows developers to pass the type as a parameter and use that type for variables, objects, classes, function parameters, etc. Let”s understand it via the example below. Example In the code below, we have a ”Wrapper” interface that takes the data type as a parameter. We have created stringWrapper and numberWrapper variables and passed string and number data types as an argument. // Define a generic interface with a single property interface Wrapper<T> { value: T; } // Use the interface with a string type let stringWrapper: Wrapper<string> = { value: “Hello, TypeScript!”, }; // Use the interface with a number type let numberWrapper: Wrapper<number> = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123 On compiling, it will generate the following JavaScript code. // Use the interface with a string type let stringWrapper = { value: “Hello, TypeScript!”, }; // Use the interface with a number type let numberWrapper = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123 Output The above example code will produce the following output – Hello, TypeScript! 123 Functions and Type Compatibility When we compare or assign one function to another function, the TypeScript compiler checks whether the target function has at least the same arguments and returns the type as the source function. If you are assigning function ”x” to function ”y”, function ”x” is a target function, and function ”y” is a source function. Additional parameters in function ”y” won”t cause any errors. Example In the code below, function ”x” contains only 1 parameter and function ”y” contains 2 parameters. When we assign function ”x” to function ”y”, additional parameter ”s” won”t cause any error. // Defining functions let x = (a: number) => { console.log(a); }; let y = (b: number, s: string) => { console.log(b + s); }; y = x; // OK // x = y; // Error: x does not accept two arguments. Classes and Type Compatibility When we compare two classes, it compares members of instances only. The class constructor and static members belong to the class itself, so those are not included in the comparison. Example In this code, we have the same instance members in variable ”a” and variable ”b”. So, when we assign variable ”a” to ”b”, it won”t raise any error. class Animal { feet: number; constructor(name: string, numFeet: number) {} } class Size { feet: number; constructor(meters: number) {} } let a: Animal; let s: Size; // Works because both classes have the same shape (they have the same instance
Category: typescript
TypeScript – Generics
TypeScript – Generics ”; Previous Next Generics are a powerful feature in TypeScript that allow you to write reusable code that can work with different types of data. They act like placeholders that can be filled with specific data types when you use the generic code. This improves code flexibility and maintainability. Problem Examples Before going deep into TypeScript generics, let”s understand the problem examples where you need to apply generics. Let”s start with the example below, where you want to log the value of the variable passed as a parameter. Example In the code below, we have defined the printVar() function which takes the number value as a parameter and logs the value in the console. Next, we invoke the function by passing 10 as an argument. function printVar(val: number) { console.log(val); // Prints the value of val } printVar(10); // Invokes the function with a number On compiling, it will generate the following JavaScript code. function printVar(val) { console.log(val); // Prints the value of val } printVar(10); // Invokes the function with a number Output Its output is as follows – 10 Now, let”s suppose you want to extend the use case of the printVar() function to print the value of other types of variables like string, boolean, etc. One way of doing that is as shown in the example below. Example In the code below, the printVar() function can accept the arguments of number, string, or boolean type. function printVar(val: number | string | boolean) { console.log(val); // Prints the value of val } printVar(true); // Invokes the function with a boolean value On compiling, it will generate the following JavaScript code. function printVar(val) { console.log(val); // Prints the value of val } printVar(true); // Invokes the function with a boolean value Output The output is as follows – true What if you want to print the array or object value? You need to extend the types of the ”val” parameter, and it makes the code complex to read. Another way to use the parameters of ”any” data type is as shown in the example below. Example In the code below, the type of the ”val” parameter is any. So, it can accept any type of value as an argument. function printVar(val: any) { console.log(val); // Prints the value of val } printVar(“Hello world!”); // Invokes the function with a boolean value On compiling, it will generate the following JavaScript code – function printVar(val) { console.log(val); // Prints the value of val } printVar(“Hello world!”); // Invokes the function with a boolean value Output Its output is as follows – Hello world! The problem with the above code is that you won”t have a reference to the data type inside the function. Whether you pass a string, number, boolean, array, etc. as a function argument, you will get the ”any” type of the variable in the function. Here, generic functions come into the picture. TypeScript Generics In TypeScript, generics is a concept that allows to creation of reusable components like functions, classes, interfaces, etc. It creates a function, classes, etc. which can work with multiple data types instead of the single data type. In short, it allows developers to create programs that can work with multiple data types and are scalable in the long term. Syntax Users can follow the syntax below to use the generic variables with functions in TypeScript. function printVar<T>(val: T) { // execute the code } printVar(val); Developers can use the type variable in the angular bracket(<>) after the function name. After that, you can use the type variable T as a type of the parameters. Here, developers can use any valid identifier instead of ”T”. After that, you can call the function with the value of any data type, and the function automatically captures the data type of the variable. Example In the example below, the printVar() function is a generic function, which takes the value of any data type as an argument, and prints it. After that, we have invoked the function with array, object, and boolean value. In the output, users can observe that it prints the value of different types of variables without any error. function printVar<T>(val: T) { // T is a generic type console.log(“data: “, val); } let arr = [1, 2, 3]; let obj = { name: “John”, age: 25 }; printVar(arr); // Val is array printVar(obj); // Val is Object printVar(true); // Val is boolean On compiling, it will generate the following JavaScript code. function printVar(val) { console.log(“data: “, val); } let arr = [1, 2, 3]; let obj = { name: “John”, age: 25 }; printVar(arr); // Val is array printVar(obj); // Val is Object printVar(true); // Val is boolean Output The output of the above example code is as follows – data: [ 1, 2, 3 ] data: { name: ”John”, age: 25 } data: true Example In this code, we printVar() function is a generic function, which takes the type of the variable value passed as a parameter. While invoking the function, we have passed the value of different data types, and users can observe the type of each variable in the output. function printVar<T>(val: T) { // T is a generic type console.log(“data: “, typeof val); } printVar(2); // Val is number printVar(“Hello”); // Val is string printVar(true); // Val is boolean On compiling, it will generate the following JavaScript code. function printVar(val) { console.log(“data: “, typeof val); } printVar(2); // Val is number printVar(“Hello”); // Val is string printVar(true); // Val is boolean Output The output of the above example code is as follows – data: number data: string data: boolean Example In the code below, the concatenate() function takes two parameters of type T and U, respectively. It uses the spread operator to concatenate the value of the ”first” and ”second” parameters. Next, we call the function to concatenate two strings and arrays. In the output, we can observe that the concatenate() function executes without
TypeScript – Operators
TypeScript – Operators ”; Previous Next What is an Operator? An operator defines some function that will be performed on the data. The data on which operators work are called operands. Consider the following expression − 7 + 5 = 12 Here, the values 7, 5, and 12 are operands, while + and = are operators. The major operators in TypeScript can be classified as − Arithmetic operators Logical operators Relational operators Bitwise operators Assignment operators Ternary/conditional operator String operator Type Operator Arithmetic Operators Assume the values in variables a and b are 10 and 5 respectively. Show Examples Operator Description Example + (Addition) returns the sum of the operands a + b is 15 – (Subtraction) returns the difference of the values a – b is 5 * (Multiplication) returns the product of the values a * b is 50 / (Division) performs division operation and returns the quotient a / b is 2 % (Modulus) performs division operation and returns the remainder a % b is 0 ++ (Increment) Increments the value of the variable by one a++ is 11 — (Decrement) Decrements the value of the variable by one a– is 9 Relational Operators Relational Operators test or define the kind of relationship between two entities. Relational operators return a Boolean value, i.e., true/ false. Assume the value of A is 10 and B is 20. Show Examples Operator Description Example > Greater than (A > B) is False < Lesser than (A < B) is True >= Greater than or equal to (A >= B) is False <= Lesser than or equal to (A <= B) is True == Equality (A == B) is false != Not equal (A != B) is True Logical Operators Logical Operators are used to combine two or more conditions. Logical operators too return a Boolean value. Assume the value of variable A is 10 and B is 20. Show Examples Operator Description Example && (And) The operator returns true only if all the expressions specified return true (A > 10 && B > 10) is False || (OR) The operator returns true if at least one of the expressions specified return true (A > 10 || B >10) is True ! (NOT) The operator returns the inverse of the expression’s result. For E.g.: !(>5) returns false !(A >10 ) is True Bitwise Operators Assume variable A = 2 and B = 3 Show Examples Operator Description Example & (Bitwise AND) It performs a Boolean AND operation on each bit of its integer arguments. (A & B) is 2 | (BitWise OR) It performs a Boolean OR operation on each bit of its integer arguments. (A | B) is 3 ^ (Bitwise XOR) It performs a Boolean exclusive OR operation on each bit of its integer arguments. Exclusive OR means that either operand one is true or operand two is true, but not both. (A ^ B) is 1 ~ (Bitwise Not) It is a unary operator and operates by reversing all the bits in the operand. (~B) is -4 << (Left Shift) It moves all the bits in its first operand to the left by the number of places specified in the second operand. New bits are filled with zeros. Shifting a value left by one position is equivalent to multiplying it by 2, shifting two positions is equivalent to multiplying by 4, and so on. (A << 1) is 4 >> (Right Shift) Binary Right Shift Operator. The left operand’s value is moved right by the number of bits specified by the right operand. (A >> 1) is 1 >>> (Right shift with Zero) This operator is just like the >> operator, except that the bits shifted in on the left are always zero. (A >>> 1) is 1 Assignment Operators Show Examples Operator Description Example = (Simple Assignment) Assigns values from the right side operand to the left side operand C = A + B will assign the value of A + B into C += (Add and Assignment) It adds the right operand to the left operand and assigns the result to the left operand. C += A is equivalent to C = C + A -= (Subtract and Assignment) It subtracts the right operand from the left operand and assigns the result to the left operand. C -= A is equivalent to C = C – A *= (Multiply and Assignment) It multiplies the right operand with the left operand and assigns the result to the left operand. C *= A is equivalent to C = C * A /= (Divide and Assignment) It divides the left operand with the right operand and assigns the result to the left operand. Note − Same logic applies to Bitwise operators, so they will become <<=, >>=, >>=, &=, |= and ^=. Miscellaneous Operators The negation operator (-) Changes the sign of a value. Let’s take an example. var x:number = 4 var y = -x; console.log(“value of x: “,x); //outputs 4 console.log(“value of y: “,y); //outputs -4 On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var x = 4; var y = -x; console.log(“value of x: “, x); //outputs 4 console.log(“value of y: “, y); //outputs -4 It will produce the following output − value of x: 4 value of y: -4 String Operators: Concatenation operator (+) The + operator when applied to strings appends the second string to the first. The following example helps us to understand this concept. var msg:string = “hello”+”world” console.log(msg) On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var msg = “hello” + “world”; console.log(msg); It will produce the following output − helloworld The concatenation operation doesn’t add a space between strings. Multiple strings can be concatenated in a single statement. Conditional Operator (?) This operator is used to represent a conditional expression. The conditional operator is also sometimes referred to as the ternary operator. The syntax is as given below
TypeScript – Abstract Classes ”; Previous Next Abstraction Classes The abstract classes are used to achieve abstraction in TypeScript. The abstract class contains only method declaration but not implementation. We need to implement all abstract methods of the abstract class into the inherited class. The abstraction is a way to hide the lower-level code implementation from users and some developers. Furthermore, it is used to show only the required information about the method rather than showing the whole complex implementation of methods. Creating Abstract Classes We can use the abstract keyword to define the abstract classes or methods. The abstract classes can contain the normal and abstract types of methods. In the abstract class, we need to implement the functional or normal method and only need to declare the abstract method. We can inherit the abstract class using any other class, but we need to implement all abstract methods of the abstract class into the inherited class. If we don’t want to implement the abstract method into the inherited class, we need to make an inherited class to abstract using the abstract keyword. Also, we can’t create the object of the abstract class, but we can create the object of the inherited class and use the abstract class methods. The limitation of the abstract class is that we can’t implement multiple inheritances using the multiple abstract classes. Syntax You can follow the syntax below to create and inherit the abstract class to other classes. abstract class sample { // define variables inside the abstract class, // declare the abstract methods or non-abstract method inside the abstract class abstract demo(string): void; } // extend sample class and implement all abstract methods of sample to demo class class test extends sample { demo(name: string): void { // code for the demo method } } Example 1 In the example below, we have defined the abstract class containing the abstract methods. In the inherited test class, we have implemented the abstract methods of the sample class. Next, we created the object of the test class with 3 arguments and used that called the demo() and save() methods. abstract class sample { // define variables inside the abstract class, property1: string; constructor(property1: string, property2: number) { this.property1 = property1; } // declare the abstract methods abstract demo(): void; // defining the non-abstract methods save(): void { console.log(“The save method of the abstract class is executed.”); } } // extend sample class and implement all abstract methods of sample to demo class class test extends sample { property2: number; constructor(property1: string, property2: number) { super(property1); this.property2 = property2; } demo(): void { // code for the demo method console.log(“The value of the property 3 is ” + this.propert2); } } let test_obj = new test(“TutorialsPont”, 9999); test_obj.demo(); test_obj.save(); We have hidden the implementation of the save() method from the inherited class test in the above example. We allow developers to implement the demo() method as they want but hide the other class information, such as property1, property2, and implementation of the save() method. Now, users understand correctly the motive to use the abstract class and how we can use it to hide the information and can reveal only the required information. On compiling, the above code will generate the following JavaScript code − var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var sample = /** @class */ (function () { function sample(property1, property2) { this.property1 = property1; } // defining the non-abstract methods sample.prototype.save = function () { console.log(“The save method of the abstract class is executed.”); }; return sample; }()); // extend sample class and implement all abstract methods of sample to demo class var test = /** @class */ (function (_super) { __extends(test, _super); function test(property1, property2) { var _this = _super.call(this, property1) || this; _this.property2 = property2; return _this; } test.prototype.demo = function () { // code for the demo method console.log(“The value of the property 3 is ” + this.propert2); }; return test; }(sample)); var test_obj = new test(“TutorialsPont”, 9999); test_obj.demo(); test_obj.save(); Output It will produce the following output − The value of the property 3 is undefined The save method of the abstract class is executed. Example 2 In the example below, the class1 is the abstract class, which contains the declaration of the abstract method name method1. The class2 only contains the definition of method2(). It extended class1 but didn’t implement the abstract method named method1(). After that, we defined class3 and inherited it via class2. Also, we have defined the method1 of class inside class3. At last, we created the object of class3 and invoked the method1() and method2(). // define the abstract class1 containing the abstract method1 abstract class class1 { abstract method1(): void; } // Need to create class2 to abstract as we inherited class1 but doesn”t defined abstract method1() abstract class class2 extends class1 { method2(): void { console.log(“Inside the method 2 of class2.”); } } // defining the class3 inherited by the class2 class class3 extends class2 { // Implementation of the method1 of the abstract class1 method1(): void { console.log( “Implemented the abstract method name method1 of class1 inside the class3” ); } } // Crating the object of the class3 var object = new class3(); // Invoking the method1 of class1 which is declared in the abstract class1 object.method1(); // Invoking the method2 of class2 object.method2(); The above example shows us that if we inherit the abstract class by any class and don’t want to implement the abstract method into the
TypeScript – Access Modifiers ”; Previous Next The concept access modifiers are used to implement encapsulation or data hiding in TypeScript. The access modifiers define the visibility class members outside the defining class. The class members are properties and functions. The access modifiers are also known as access specifiers. TypeScript supports three types of access modifiers – public, private and protected. These modifiers are the keywords that are used to declare a class member as public, private or protected. A public class member is accessible from anywhere in the code. A private member is only accessible within the class that defines it. And a protected member is accessible from within the class and derived classes. Let”s understand each of the three access modifiers discussed above in details. Public Access Modifier A public access modifier in TypeScript defines a public class member. By default, a member of class is public. So it”s optional to use public keyword to declare a member public. The public members are accessible from anywhere within and outside the class that defines the member. Example In the example below, we have created a class named Person. The class Person has two members, one a public property name and other a public method greet(). As these members are declared as public, these can be accessed from anywhere in the program. We also created an instance of the Person class as person. We access the name property of the person object and assign a value to it. Finally, we called the greet function to display the greeting with new name. class Person { public name: string = “”; public greet(): void { console.log(`Hello, my name is ${this.name}!`); } } const person = new Person(); person.name = “John”; person.greet(); On compiling, it will generate the following JavaScript code. class Person { constructor() { this.name = “”; } greet() { console.log(`Hello, my name is ${this.name}!`); } } const person = new Person(); person.name = “John”; person.greet(); The output of the above example code is as follows – Hello, my name is John! Private Access Modifiers A private access modifier restricts the access of the class member (property or method) to the class where it is declared. When you add the private modifier to the property or method, you can access that property or method within the same class only. A private access modifier in TypeScript defines a private class member. Private members are accessible from within the class that defines them. Example In this example, we have created a BankAccount class with a private property balance, which can only be accessed and modified within the class. Additionally, we have a private method calculateInterest(), that calculates the interest based on the balance. You can observe in the output that attempting to access the private members will result in a TypeError. class BankAccount { private balance: number; constructor(initialBalance: number) { this.balance = initialBalance; } private calculateInterest(): number { const interestRate = 0.05; return this.balance * interestRate; } } // Creating an instance of the BankAccount class const account = new BankAccount(1000); // Attempting to access private members console.log(account.balance); console.log(account.calculateInterest()); On compiling, it will generate the following JavaScript code. class BankAccount { constructor(initialBalance) { this.balance = initialBalance; } calculateInterest() { const interestRate = 0.05; return this.balance * interestRate; } } // Creating an instance of the BankAccount class const account = new BankAccount(1000); // Attempting to access private members console.log(account.balance); console.log(account.calculateInterest()); And it will give the following error – Property ”balance” is private and only accessible within class ”BankAccount”. Property ”calculateInterest” is private and only accessible within class ”BankAccount”. The output of the above example code is as follows – 1000 50 Protected Access Modifiers The protected access modifier is used to define a protected class member (property or method). A protected data member is accessible only within the class that defines it or any class that extends it. Example In this example, we create a base class Animal with a protected property name, which can be accessed and modified within the class and its derived classes. We also have a protected method makeSound(), that simply logs a message. We then create a derived class Dog that extends the Animal class. The Dog class adds a public method bark(), which utilizes the name property inherited from the base class to output a bark message. Finally, we create an instance of the Dog class named dog with the name “Buddy” and call the bark() method. The output will show the dog”s name followed by the bark message. class Animal { protected name: string; constructor(name: string) { this.name = name; } protected makeSound(): void { console.log(“The animal makes a sound”); } } class Dog extends Animal { public bark(): void { console.log(`${this.name} barks!`); } } // Creating an instance of the Dog class const dog = new Dog(“Buddy”); dog.bark(); On compiling, it will generate the following JavaScript code. class Animal { constructor(name) { this.name = name; } makeSound() { console.log(“The animal makes a sound”); } } class Dog extends Animal { bark() { console.log(`${this.name} barks!`); } } // Creating an instance of the Dog class const dog = new Dog(“Buddy”); dog.bark(); The output of the above example code is as follows – Buddy barks! Print Page Previous Next Advertisements ”;
TypeScript – Union
TypeScript – Union ”; Previous Next TypeScript gives programs the ability to combine one or two types. Union types are a powerful way to express a value that can be one of the several types. Two or more data types are combined using the pipe symbol (|) to denote a Union Type. In other words, a union type is written as a sequence of types separated by vertical bars. Syntax: Union literal We use pipe symbol (|) to combine two or more types to achieve a union type in TypeScript − Type1 | Type2 | Type3 Union Type Variable We can define a variable of type union of different types. For example, let value: number | string | boolean; In the above example, we define a variable named value of union type. We can assign numeric, string or boolean value to the variable. Example: Union Type Variable In the example below, the variable”s type is union. It means that the variable can contain either a number or a string as its value. var val: string | number val = 12 console.log(“numeric value of val: “+val) val = “This is a string” console.log(“string value of val: “+val) On compiling, it will generate following JavaScript code. var val; val = 12; console.log(“numeric value of val: ” + val); val = “This is a string”; console.log(“string value of val: ” + val); Its output of the above example code is as follows − numeric value of val: 12 string value of val: this is a string Union Type and Function Parameter We can define a function with a parameter of union type. When you can call the function, you can pass the argument of any type of union type. For example, function display(name: string | string[]){ // function body; } In the above code snippet, function display() has parameter of union type (string or string array). You can call the function passing argument either a string or an array of string. Example In the example below, we defined a function named disp with a parameter of union type. The function disp() can accept argument either of the type string or a string array. function disp(name: string|string[]) { if(typeof name == “string”) { console.log(name) } else { var i; for(i = 0;i<name.length;i++) { console.log(name[i]) } } } disp(“mark”) console.log(“Printing names array….”) disp([“Mark”,”Tom”,”Mary”,”John”]) On compiling, it will generate following JavaScript code. function disp(name) { if (typeof name == “string”) { console.log(name); } else { var i; for (i = 0; i < name.length; i++) { console.log(name[i]); } } } disp(“mark”); console.log(“Printing names array….”); disp([“Mark”, “Tom”, “Mary”, “John”]); The output is as follows − Mark Printing names array…. Mark Tom Mary John Union Type and Arrays Union types can also be applied to arrays, properties and interfaces. The following illustrates the use of union type with an array. Example The program declares an array. The array can represent either a numeric collection or a string collection. var arr: number[]|string[]; var i: number; arr = [1,2,4] console.log(“**numeric array**”) for(i = 0;i<arr.length;i++) { console.log(arr[i]) } arr = [“Mumbai”,”Pune”,”Delhi”] console.log(“**string array**”) for(i = 0;i<arr.length;i++) { console.log(arr[i]) } On compiling, it will generate following JavaScript code. var arr; var i; arr = [1, 2, 4]; console.log(“**numeric array**”); for (i = 0; i < arr.length; i++) { console.log(arr[i]); } arr = [“Mumbai”, “Pune”, “Delhi”]; console.log(“**string array**”); for (i = 0; i < arr.length; i++) { console.log(arr[i]); } Its output is as follows − **numeric array** 1 2 4 **string array** Mumbai Pune Delhi Print Page Previous Next Advertisements ”;
TypeScript – null vs. undefined ”; Previous Next In TypeScript, ”undefined” denotes that a variable has been declared but has not been assigned any value. On the other hand, ”null” refers to a non-existent object which is basically ”empty” or ”nothing”. Have you ever faced a scenario where you need to declare the variable but need to initialize it later? It generally happens while dealing with the APIs where you need to initialize the variables after getting an API response. In such cases, you can use the null or undefined data types to represent the absence of values. What is null? In TypeScript, ”null” is a primitive value, which represents the no value assigned to the variable. It is explicitly assigned to the variable to indicate the variable is empty or doesn”t contain any value. Let”s understand how to use the ”null” in TypeScript via the examples below. Example: Basic use of null In the code below, we have defined a variable of ”null” type. It represents the variable ”a” contains an empty value. In the output, you can observe that it prints a null value. // Using null value let a: null = null; console.log(a); // null On compiling, it will generate the following JavaScript code. // Using null value let a = null; console.log(a); // null The ouput of the above code is as follows – null Example: Data type of null The data type of the ”null” type variable is an object. Here, we have used the ”typeof” operator to check the data type of the variable containing the null value. It returns the object which you can observe in the output. let a: null = null; console.log(typeof a); // Object On compiling, it will generate the following JavaScript code. let a = null; console.log(typeof a); // Object The output of the above code is as follows – object Example: Reinitializing null variable In the code below, the data type of the variable ”a” is either number or null. Initially, we have assigned a null value to that. After that, we have assigned the number value to the variable ”a”. let a: number | null = null; console.log(“The initial value of the variable a is: ” + a); // null a = 10; console.log(“The value of the variable a is: ” + a); // 10 On compiling, it will generate the following JavaScript code. let a = null; console.log(“The initial value of the variable a is: ” + a); // null a = 10; console.log(“The value of the variable a is: ” + a); // 10 Its output is as follows – The initial value of the variable a is: null The value of the variable a is: 10 What is undefined? When you declare the variable but don”t assign any value, TypeScript automatically assigns the ”undefined” value to the variable. Whenever you don”t return anything from the function, it returns the undefined value. However, you can also explicitly assign an undefined value to the variable of type ”undefined”. Let”s understand about undefined via the examples below. Example: Undefined Values In the code below, we have defined the variable ”a” but haven”t initialized it with the value. So, its value is undefined which you can see in the output. let a: number; console.log(“The value of a is ” + a); On compiling, it will show the following error – Variable ”a” is used before being assigned. And also it will generate the following JavaScript code. let a; console.log(“The value of a is ” + a); The output of the above JavaScript code is as follows – The value of a is undefined Example: Not returning a value from the function In the code below, we have defined the greet() function which doesn”t return any value. After that, we invoked the greet() function and stored its outcomes in the variable ”a”. The value of the variable is undefined as the greet() function doesn”t return any value. // Not returning a value from the function function greet(name: string): void { console.log(`Hello ${name}`); } let a = greet(”John”); console.log(a); // undefined On compiling, it will generate the following JavaScript code. // Not returning a value from the function function greet(name) { console.log(`Hello ${name}`); } let a = greet(”John”); console.log(a); // undefined The output of the above code is as follows – Hello John Undefined Example: Using the undefined type Here, we have used the ”undefined” data type with the variable ”a” and assigned an undefined value to it. The type of the variable ”a” is undefined but not object as like the ”null” type variables. let a: undefined = undefined; console.log(a); // undefined console.log(typeof a); // undefined On compiling, it will generate the following JavaScript code. let a = undefined; console.log(a); // undefined console.log(typeof a); // undefined The output is as follows – undefined undefined Null vs. Undefined: Key Differences You learned about Null and Undefined. Now, let”s look at the key differences between them. Feature null undefined Meaning Explicitly no value Not initialized Typical Use Intentionally empty or absent value Variable declared but not yet assigned Type Annotation Has its own type null Has its own type undefined Default Behavior Does not trigger default function parameters Triggers default function parameters Function Parameters Used to denote explicitly that parameter should not have a value Indicates missing parameters or optional parameters Object Properties Can be used to indicate properties that are deliberately set to no value Used for properties that may not be initialized Operational Handling Must be handled explicitly in logic to avoid errors Often handled with default values or optional chaining Let”s look at the examples below which shows where to use null and undefined values. Example: Object Properties In the code below, the ”user” type has ”name”, ”age”, and ”email” properties. The ”age” property can accept a null value if the user”s age is not available. The ”email” property is optional so it”s fine if we don”t use it while defining the object. The
TypeScript – Extending Interfaces ”; Previous Next In TypeScript, interfaces are a powerful way to define the shape of objects and enforce type constraints. They allow us to specify the required properties and methods that an object must have. One interesting feature of interfaces is the ability to extend them, allowing us to create a combination of interfaces. Extending an interface is also known as interface inheritance. Interface inheritance allows you to create more specialized interfaces that inherit properties and methods from other interfaces. Syntax Use extends keyword to extend a single or multiple interfaces in TypeScript. interface NewInterface extends ExistingInterface { // Additional properties and methods } interface NewInterface extends Interface1, Interface2, … { // Additional properties and methods } The syntax to create a new interface by extending an existing one is shown above. The syntax for extending multiple interfaces is also shown. The second syntax is to extend multiple interfaces. Extending a Single Interface We can achieve single interface inheritance by extending a single interface. Let”s start with a simple scenario where we have an interface called Shape that defines a common property color for various shapes. We want to create a new interface ColoredShape that extends Shape and adds an additional property name. Example Let”s see an example of extending the Shape interface to create the ColoredShape interface. In this example, we defined the Shape interface with a color property. Then, we created the ColoredShape interface by extending Shape and adding a name property. We instantiated an object square of type ColoredShape and assigned values to color and name properties. Finally, we accessed and printed the values of color and name using dot notation. interface Shape { color: string; } interface ColoredShape extends Shape { name: string; } const square: ColoredShape = { color: “red”, name: “Square”, }; console.log(square.color); console.log(square.name); On compiling, it will generate the following JavaScript code: var square = { color: “red”, name: “Square” }; console.log(square.color); console.log(square.name); Output red Square Extending Multiple Interfaces In TypeScript, we can also extend multiple interfaces to create a new interface that combines properties and methods from all the extended interfaces. This allows us to create more complex and specialized interfaces by reusing existing ones. This helps to achieve multiple interface inheritance in TypeScript. Example In the example below, we defined the Printable and Scanable interfaces, each with their respective methods. Then, we created the MultifunctionalDevice interface by extending both Printable and Scanable interfaces and adding a new method copy(). We implemented the MultifunctionalDevice interface in a class called Printer and provided the necessary implementations for all the methods. Finally, we instantiated an object of the Printer class and called the print(), scan(), and copy() methods. interface Printable { print(): void; } interface Scanable { scan(): void; } interface MultifunctionalDevice extends Printable, Scanable { copy(): void; } class Printer implements MultifunctionalDevice { print() { console.log(“Printing…”); } scan() { console.log(“Scanning…”); } copy() { console.log(“Copying…”); } } const printer = new Printer(); printer.print(); printer.scan(); printer.copy(); On compiling, it will generate the following JavaScript code: var Printer = /** @class */ (function () { function Printer() { } Printer.prototype.print = function () { console.log(“Printing…”); }; Printer.prototype.scan = function () { console.log(“Scanning…”); }; Printer.prototype.copy = function () { console.log(“Copying…”); }; return Printer; }()); var printer = new Printer(); printer.print(); printer.scan(); printer.copy(); Output Printing… Scanning… Copying… Enhancing an Existing Interface We may often encounter situations where we want to enhance an existing interface by adding additional properties or methods. Extending the interface allows us to do so without modifying the original interface directly. Example In this example, we have an existing User interface with a name property. We extend the User interface to create an EnhancedUser interface, which adds an age property and a greet() method. By extending the interface, we can define an object user of type EnhancedUser that includes the properties and methods from both interfaces. interface User { name: string; } interface EnhancedUser extends User { age: number; greet(): void; } const user: EnhancedUser = { name: “John Wick”, age: 25, greet() { console.log(`Hello, my name is ${this.name} and I”m ${this.age} years old.`); } }; user.greet(); On compiling, it will generate the following JavaScript code: var user = { name: “John Wick”, age: 25, greet: function () { console.log(“Hello, my name is “.concat(this.name, ” and I”m “).concat(this.age, ” years old.”)); } }; user.greet(); Output Hello, my name is John Wick and I”m 25 years old. Creating Composite Interfaces Extending interfaces can also be valuable when creating composite interfaces that combine properties and methods from multiple sources. This is particularly useful when working with external libraries or modules that provide their interfaces. Example In this example, we have four interfaces: Product, DiscountedProduct, ProductWithReviews, and FeaturedProduct. Each interface extends one or more existing interfaces, allowing us to create a composite interface with properties and methods from multiple sources. We then define an object product of the type FeaturedProduct, which incorporates all the properties defined in the extended interfaces. interface Product { name: string; price: number; } interface DiscountedProduct extends Product { discount: number; } interface ProductWithReviews extends Product { reviews: string[]; } interface FeaturedProduct extends DiscountedProduct, ProductWithReviews { featured: boolean; } const product: FeaturedProduct = { name: “Smartphone”, price: 599, discount: 50, reviews: [“Great product!”, “Highly recommended.”], featured: true }; console.log(product.featured); console.log(product.reviews); On compiling, it will generate the following JavaScript code: var product = { name: “Smartphone”, price: 599, discount: 50, reviews: [“Great product!”, “Highly recommended.”], featured: true }; console.log(product.featured); console.log(product.reviews); Output true [ ”Great product!”, ”Highly recommended.” ] Overriding Properties and Methods We can also override properties and methods inherited from the base interfaces when extending interfaces. This allows us to modify or provide different implementations for specific properties or methods in the extended interface. Example In the below example, we have an Animal interface with a name property and a makeSound() method. We extend the Animal interface to create a Dog interface. By overriding the makeSound() method in the Dog interface, we provide a different implementation
TypeScript – Decision Making
TypeScript – Decision Making ”; Previous Next In TypeScript, the decision making statements are used to control the flow of the execution based on certain conditions. TypeScript support all types of decision making constructs available in ES6, including if, if else, switch statements. As a superset of JavaScript, TypeScript inherits and expands upon JavaScript’s features including decision-making statements. Decision-making structures require that the programmer specifies one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false. Shown below is the general form of a typical decision-making structure found in most of the programming languages − A decision-making construct evaluates a condition before the instructions are executed. Decision-making constructs in TypeScript are classified as follows − S.No. Statement & Description 1. if statement An ‘if’ statement consists of a Boolean expression followed by one or more statements. 2. if…else statement An ‘if’ statement can be followed by an optional ‘else’ statement, which executes when the Boolean expression is false. 3. else…if and nested if statements You can use one ‘if’ or ‘else if’ statement inside another ‘if’ or ‘else if’ statement(s). 4. switch statement A ‘switch’ statement allows a variable to be tested against a list of values. Examples Let”s understand the decision making in detail with the help of some examples in TypeScript. Example: If Statement In the example below, the if statement checks the condition “age >= 18”. The condition (boolean expression) is true so the statement within curly brackets ({}) is executed. let age: number = 19; if (age >= 18) { console.log(“You care eligible for voting.”); } On compiling it will generate the following JavaScript code. let age = 19; if (age >= 18) { console.log(“You care eligible for voting.”); } The output of the above example code is as follows – You are eligible for voting. So what if the condition (boolean expression) age >= 18 is evaluated as false. If the condition is false, else statement will be executed. Let’s check the flowing example – Example: If…else statement In this example, the condition (age >= 18) is evaluated to false so the statement following the else statement is executed. let age: number = 17; if (age >= 18) { console.log(“You care eligible for voting.”); } else { console.log(“You are not eligible for voting.”) } On compiling, it will generate the following JavaScript code. let age = 17; if (age >= 18) { console.log(“You care eligible for voting.”); } else { console.log(“You are not eligible for voting.”) } The output of the above example code is as follows – You are not eligible for voting. Example: Nested if statements In the example below, else…if ladder used to check multiple conditions. The condition grade >= 80 evaluates to true so it will print “You got a B grade” in the console. var grade: number = 85; if (grade >= 90) { console.log(“You got an A grade”); } else if (grade >= 80) { console.log(“You got a B grade “); } else if (grade >= 70) { console.log(“You got a C grade “); } else if (grade >= 60) { console.log(“You got a D grade “); } else { console.log(“You got an F grade “); } On compiling, it will generate the following JavaScript code. var grade = 85; if (grade >= 90) { console.log(“You got an A grade”); } else if (grade >= 80) { console.log(“You got a B grade “); } else if (grade >= 70) { console.log(“You got a C grade “); } else if (grade >= 60) { console.log(“You got a D grade “); } else { console.log(“You got an F grade “); } The output of the above example code is as follows – You got a B grade Example: Switch statement The example below, we use the grade variable as an expression of switch case statement. It verifies the value of grade against the case constants (A, B and C) and executes the corresponding block. If value of grade does not match with any case value, the default case will be executed. var grade: string = ”B”; switch (grade) { case ”A”: { console.log(“Excellent”); break; } case ”B”: { console.log(“Good”); break; } case ”C”: { console.log(“Fair”); break; } default: console.log(“Unknown grade”); } On compiling, it will generate the following JavaScript code. var grade = ”B”; switch (grade) { case ”A”: { console.log(“Excellent”); break; } case ”B”: { console.log(“Good”); break; } case ”C”: { console.log(“Fair”); break; } default: console.log(“Unknown grade”); } The output of the above example code is as follows – Good Print Page Previous Next Advertisements ”;
TypeScript – Duck-Typing
TypeScript – Duck Typing ”; Previous Next Duck Typing The circumstance where an object”s type is decided by its behavior, like methods and attributes, rather than its class is known as “duck typing”. The usage of interfaces in TypeScript makes duck typing possible. Where interface means the set of methods and characteristics an object must have to fall under that type are described. For example, if an interface defines the function, any object with the method called “myFunc()” may be treated as belonging to a specific kind, regardless of its class. Duck typing emphasizes assessing an object”s suitability for a task by considering its methods and attributes instead of its actual type. An interface explains the set of properties and methods an object must have to be considered “duck typed” for a particular purpose. Benefits of Duck Typing One of duck typing”s main benefits is making code more flexible and reusable. The code works with any object with the required methods and properties rather than just particular types of objects and may be used in various situations without requiring modification. Duck typing also improves code reuse by enabling the interchangeable usage of objects of diverse kinds within a single codebase. Exmaples of Duck Typing is TypeScript Here is an example of how to use duck typing in TypeScript − Define an interface that represents the behaviour you want an object to have. For example − interface Duck { quack(): void; } Create a class that implements the interface. For example − class MallardDuck implements Duck { quack(): void { console.log(“Quack!”); } } Create an instance of the class and use it as the type defined by the interface. let duck: Duck = new MallardDuck(); duck.quack(); // Output: “Quack!” Create another class that also implements the interface − class RubberDuck implements Duck { quack(): void { console.log(“Squeak!”); } } Use the new class instance as the same type defined by the interface. let duck: Duck = new RubberDuck(); duck.quack(); // Output: “Squeak!” As you can see, both MallardDuck and RubberDuck classes implement the Duck interface, and the duck variable can be assigned to instances of both classes. The type is determined by the behaviour (methods and properties) defined in the interface rather than the class. It”s also important to note that in typescript, you can use the typeof keyword to check the type of object in runtime and if the object has the expected method or property. Example In this example, the Bird and Plane classes implement the Flyable interface, which requires a fly() method. Both “duck types” can be used interchangeably in the goFly() function. The function doesn”t care about the actual type of the object passed to it as long as it has a fly() method that can be called. interface Flyable { fly(): void; } class Bird implements Flyable { fly(): void { console.log(“Bird is flying”); } } class Plane implements Flyable { fly(): void { console.log(“Plane is flying”); } } function goFly(flyable: Flyable) { flyable.fly(); } let bird = new Bird(); let plane = new Plane(); goFly(bird); // Prints “Bird is flying” goFly(plane); // Prints “Plane is flying” On compiling, it will generate the following JavaScript code − var Bird = /** @class */ (function () { function Bird() { } Bird.prototype.fly = function () { console.log(“Bird is flying”); }; return Bird; }()); var Plane = /** @class */ (function () { function Plane() { } Plane.prototype.fly = function () { console.log(“Plane is flying”); }; return Plane; }()); function goFly(flyable) { flyable.fly(); } var bird = new Bird(); var plane = new Plane(); goFly(bird); // Prints “Bird is flying” goFly(plane); // Prints “Plane is flying” Output The above code will produce the following output – Bird is flying Plane is flying Example Overall, duck typing is a powerful programming concept that allows for greater flexibility and reusability in TypeScript code by allowing objects of different types to be used interchangeably as long as they have the same methods and properties. In this example, the Driveable interface, Car and Truck classes show the same thing. interface Driveable { drive(): void; } class Car implements Driveable { drive(): void { console.log(“Car is driving”); } } class Truck implements Driveable { drive(): void { console.log(“Truck is driving”); } } function goDrive(driveable: Driveable) { driveable.drive(); } let car = new Car(); let truck = new Truck(); goDrive(car); // Prints “Car is driving” goDrive(truck); // Prints “Truck is driving” On compiling, it will generate the following JavaScript code − var Car = /** @class */ (function () { function Car() { } Car.prototype.drive = function () { console.log(“Car is driving”); }; return Car; }()); var Truck = /** @class */ (function () { function Truck() { } Truck.prototype.drive = function () { console.log(“Truck is driving”); }; return Truck; }()); function goDrive(driveable) { driveable.drive(); } var car = new Car(); var truck = new Truck(); goDrive(car); // Prints “Car is driving” goDrive(truck); // Prints “Truck is driving” Output The above code will produce the following output – Car is driving Truck is driving The main idea behind duck typing is that the code should be written to work with any object with the methods and properties it needs, rather than being written to work with specific objects. This can make the code more flexible and reusable, allowing you to use different types of objects interchangeably without changing the code. Print Page Previous Next Advertisements ”;