TypeScript – Type Inference ”; Previous Next Type inference is a feature in TypeScript that allows the compiler to automatically determine (infer) the type of a variable, function or expression. TypeScript is an optionally static type programming language. You can declare variables, expressions, or functions without explicitly annotating their types. The compiler will automatically determine the types at the compile time. The type inference can be done on the basis of a number of factors, including – The type of values assigned to the variables. The type of function parameters or arguments passed to the function. The type of return value of the function. The types of the object and properties. Let”s take a simple example as follows – let x = 5; let y = “Hello World!”; In the above code, the TypeScript compiler can infer that the type of variable x is number. This is because the variable x is being assigned a number. The compiler can also infer the type of y is string because the y is being assigned a string. In the above example, TypeScript automatically infers the types of variables based on the values assigned to them. Variable or Member Initialization The type inference can be inferred using the variable and member initialization. The TypeScript compiler infers the type of the variable from the initialized value. Example Let”s take an example of variable initialization as follows – let x = 20; let y = “Hello World!”; let z = true; console.log(“type of x: “, typeof x); console.log(“type of y: “, typeof y); console.log(“type of z: “, typeof z); On compilation, it will generate the same JavaScript code. The output of the above example code is as follows – type of x: number type of y: string type of z: boolean Let’s have an example of object member initialization – class Person { name = “Shahid”; age = 35; } const p = new Person(); // Prints name and age console.log(`${p.name}, ${p.age}`); On compilation, it will generate following JavaScript code. class Person { constructor() { this.name = “Shahid”; this.age = 35; } } const p = new Person(); // Prints name and age console.log(`${p.name}, ${p.age}`); The output of the above code is as follows – Shahid, 35 Function Default Parameter The typescript compiler can also infer the type of the function parameters when the parameters are initialized with default values. In the below example, the parameters x and y are initialized with default values. The compiler infers the type of x and y as number. This is because the initialized values are numbers. function add(x = 10, y = 30){ return x + y; } let res = add(2,3); console.log(res); On compilation, it will generate the same code in JavaScript. The output of the above example code is as follows – 5 Now let”s try to pass arguments as string values. let res2 = add(”2”, ”3”); The type of the parameters of the function add are inferred as number so when we pass arguments of type string to the function, it shows the following error – Argument of type ”string” is not assignable to parameter of type ”number”. Function Return Type The TypeScript compiler infers the type of the return type of the function based on the type of the return value. If the function doesn”t return any value, then the return type is void. In the example below, the function add accepts the two numbers and return their sum. As the sum of two numbers are number, so the type of return value is number. Hence the compiler infers the return type of the function add as number. function add(x: number, y: number){ return x + y; } let res1: number = add(2,3); console.log(res1); When we assign the return value of the function add to variable (res2) of type string, it will show an error. let res2: string = add(2,3); The error is as follows – Type ”number” is not assignable to type ”string”. This is because the return type of the function add is number and we are assigning it to variable of string type. Best Common Type: The Union Type Type inference with variable initialization, function default parameters and return type is straightforward. When TypeScript infers a type from multiple expressions, the type of the expressions is determined as the “best common type”. Let”s understand this with the help of an example – const a = [5, 10, “TypeScript”]; In the above example, the array contains values – 5, 10, and “TypeScript”. To infer the type of the array, we must consider the type of each element. Here, we have choices for the type of the array as number, and string. The inferred type of the array should be the best common type for each value in the array. The best common type has to be chosen from the provided candidate type. If there is no super type of all candidate types, the union type is used. Hence the inferred type of the above array is – (number | string)[] The above array can contain values of types number, and string only. If you try to add a value of type different from number and string, it will show an error. Let”s try to add a boolean value to the array. const a = [5, 10, “TypeScript”]; a.push(true); The above code will show the following compilation error – Argument of type ”boolean” is not assignable to parameter of type ”string | number”. Contextual Typing Contextual typing is a feature in TypeScript that allows the compiler to infer the type of variable, parameter or expression based on the context where they are used. For example, window.onmousedown = function (mouseEvent) { console.log(mouseEvent.button); } In the above example, the TypeScript infers the type the function expression on right hand side of the assignment using the type of the Window.onmousedown function. So it is able to infer the type of mouseEvent parameter as MouseEvent. This way TypeScript infers that mouseEvent has a
Category: typescript
TypeScript – Modules
TypeScript – Modules ”; Previous Next A module is designed with the idea to organize code written in TypeScript. Modules are broadly divided into − Internal Modules External Modules Internal Module Internal modules came in earlier version of Typescript. This was used to logically group classes, interfaces, functions into one unit and can be exported in another module. This logical grouping is named namespace in latest version of TypeScript. So internal modules are obsolete instead we can use namespace. Internal modules are still supported, but its recommended to use namespace over internal modules. Internal Module Syntax (Old) module TutorialPoint { export function add(x, y) { console.log(x+y); } } Namespace Syntax (New) namespace TutorialPoint { export function add(x, y) { console.log(x + y);} } JavaScript generated in both cases are same var TutorialPoint; (function (TutorialPoint) { function add(x, y) { console.log(x + y); } TutorialPoint.add = add; })(TutorialPoint || (TutorialPoint = {})); External Module External modules in TypeScript exists to specify and load dependencies between multiple external js files. If there is only one js file used, then external modules are not relevant. Traditionally dependency management between JavaScript files was done using browser script tags (<script></script>). But that’s not extendable, as its very linear while loading modules. That means instead of loading files one after other there is no asynchronous option to load modules. When you are programming js for the server for example NodeJs you don’t even have script tags. There are two scenarios for loading dependents js files from a single main JavaScript file. Client Side – RequireJs Server Side – NodeJs Selecting a Module Loader To support loading external JavaScript files, we need a module loader. This will be another js library. For browser the most common library used is RequieJS. This is an implementation of AMD (Asynchronous Module Definition) specification. Instead of loading files one after the other, AMD can load them all separately, even when they are dependent on each other. Defining External Module When defining external module in TypeScript targeting CommonJS or AMD, each file is considered as a module. So it’s optional to use internal module with in external module. If you are migrating TypeScript from AMD to CommonJs module systems, then there is no additional work needed. The only thing you need to change is just the compiler flag Unlike in JavaScript there is an overhead in migrating from CommonJs to AMD or vice versa. The syntax for declaring an external module is using keyword ‘export’ and ‘import’. Syntax //FileName : SomeInterface.ts export interface SomeInterface { //code declarations } To use the declared module in another file, an import keyword is used as given below. The file name is only specified no extension used. import someInterfaceRef = require(“./SomeInterface”); Example Let’s understand this using an example. // IShape.ts export interface IShape { draw(); } // Circle.ts import shape = require(“./IShape”); export class Circle implements shape.IShape { public draw() { console.log(“Cirlce is drawn (external module)”); } } // Triangle.ts import shape = require(“./IShape”); export class Triangle implements shape.IShape { public draw() { console.log(“Triangle is drawn (external module)”); } } // TestShape.ts import shape = require(“./IShape”); import circle = require(“./Circle”); import triangle = require(“./Triangle”); function drawAllShapes(shapeToDraw: shape.IShape) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle()); The command to compile the main TypeScript file for AMD systems is − tsc –module amd TestShape.ts On compiling, it will generate following JavaScript code for AMD. File:IShape.js //Generated by typescript 1.8.10 define([“require”, “exports”], function (require, exports) { }); File:Circle.js //Generated by typescript 1.8.10 define([“require”, “exports”], function (require, exports) { var Circle = (function () { function Circle() { } Circle.prototype.draw = function () { console.log(“Cirlce is drawn (external module)”); }; return Circle; })(); exports.Circle = Circle; }); File:Triangle.js //Generated by typescript 1.8.10 define([“require”, “exports”], function (require, exports) { var Triangle = (function () { function Triangle() { } Triangle.prototype.draw = function () { console.log(“Triangle is drawn (external module)”); }; return Triangle; })(); exports.Triangle = Triangle; }); File:TestShape.js //Generated by typescript 1.8.10 define([“require”, “exports”, “./Circle”, “./Triangle”], function (require, exports, circle, triangle) { function drawAllShapes(shapeToDraw) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle()); }); The command to compile the main TypeScript file for Commonjs systems is tsc –module commonjs TestShape.ts On compiling, it will generate following JavaScript code for Commonjs. File:Circle.js //Generated by typescript 1.8.10 var Circle = (function () { function Circle() { } Circle.prototype.draw = function () { console.log(“Cirlce is drawn”); }; return Circle; })(); exports.Circle = Circle; File:Triangle.js //Generated by typescript 1.8.10 var Triangle = (function () { function Triangle() { } Triangle.prototype.draw = function () { console.log(“Triangle is drawn (external module)”); }; return Triangle; })(); exports.Triangle = Triangle; File:TestShape.js //Generated by typescript 1.8.10 var circle = require(“./Circle”); var triangle = require(“./Triangle”); function drawAllShapes(shapeToDraw) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle()); Output Cirlce is drawn (external module) Triangle is drawn (external module) Print Page Previous Next Advertisements ”;
TypeScript – Utility Types
TypeScript – Utility Types ”; Previous Next TypeScript allows us to create a new type from the existing types, and we can use the utility types for such transformation. There are various utility types that exist in TypeScript, and we can use any utility type according to our requirements of the type transformation. Let”s discus the different utility types with examples in TypeScript. Partial Type in TypeScript The Partial utility type transforms all the properties of the current type to optional. The meaning of the partial is either all, some, or none. So, it makes all properties optional, and users can use it while refactoring the code with objects. Example In the example below, we have created the Type containing some optional properties. After that, we used the Partial utility type to create a partialType object. Users can see that we haven’t initialized all the properties of the partialType object, as all properties are optional. type Type = { prop1: string; prop2: string; prop3: number; prop4?: boolean; }; let partialType: Partial<Type> = { prop1: “Default”, prop4: false, }; console.log(“The value of prop1 is ” + partialType.prop1); console.log(“The value of prop2 is ” + partialType.prop2); On compiling, it will generate the following JavaScript code − var partialType = { prop1: “Default”, prop4: false }; console.log(“The value of prop1 is ” + partialType.prop1); console.log(“The value of prop2 is ” + partialType.prop2); Output The above code will produce the following output − The value of prop1 is Default The value of prop2 is undefined Required Type in TypeScript The Required utility type allows us to transform type in such a way that it makes all properties of the type required. When we use the Required utility type, it makes all optional properties to required properties. Example In this example, Type contains the prop3 optional property. After transforming the Type using the Required utility operator, prop3 also became required. If we do not assign any value to the prop3 while creating the object, it will generate a compilation error. type Type = { prop1: string; prop2: string; prop3?: number; }; let requiredType: Required<Type> = { prop1: “Default”, prop2: “Hello”, prop3: 40, }; console.log(“The value of prop1 is ” + requiredType.prop1); console.log(“The value of prop2 is ” + requiredType.prop2); On compiling, it will generate the following JavaScript code − var requiredType = { prop1: “Default”, prop2: “Hello”, prop3: 40 }; console.log(“The value of prop1 is ” + requiredType.prop1); console.log(“The value of prop2 is ” + requiredType.prop2); Output The above code will produce the following output − The value of prop1 is Default The value of prop2 is Hello Pick Type in TypeScript The Pick utility type allows us to pick a type of properties of other types and create a new type. Users need to use the key of the types in the string format to pick the key with their type to include in the new type. Users should use the union operator if they want to pick multiple keys with their type. Example In the example below, we have picked the color and id properties from type1 and created the new type using the Pick utility operator. Users can see that when they try to access the size property of the newObj, it gives an error as a type of newObj object doesn’t contain the size property. type type1 = { color: string; size: number; id: string; }; let newObj: Pick<type1, “color” | “id”> = { color: “#00000”, id: “5464fgfdr”, }; console.log(newObj.color); // This will generate a compilation error as a type of newObj doesn”t contain the size property // console.log(newObj.size); On compiling, it will generate the following JavaScript code − var newObj = { color: “#00000”, id: “5464fgfdr” }; console.log(newObj.color); // This will generate a compilation error as a type of newObj doesn”t contain the size property // console.log(newObj.size); Output The above code will produce the following output − #00000 Omit Type in TypeScript The Omit removes the keys from the type and creates a new type. It is the opposite of the Pick. Whatever key we use with the Omit utility operator removes those keys from the type and returns a new type. Example In this example, we have omitted the color and id properties from the type1 using the Omit utility type and created the omitObj object. When a user tries to access the color and id properties of omitObj, it will generate an error. type type1 = { color: string; size: number; id: string; }; let omitObj: Omit<type1, “color” | “id”> = { size: 20, }; console.log(omitObj.size); // This will generate an error // console.log(omitObj.color); // console.log(omitObj.id) On compiling, it will generate the following JavaScript code − var omitObj = { size: 20 }; console.log(omitObj.size); // This will generate an error // console.log(omitObj.color); // console.log(omitObj.id) Output The above code will produce the following output − 20 Readonly Type in TypeScript We can use the Readonly utility type to make all types read-only properties, making all properties immutable. So, we can’t assign any value to the readonly properties after initializing for the first time. Example In this example, keyboard_type contains three different properties. We have used the Readonly utility type to make all properties of keyboard objects read-only. The read-only property means we can access it to read values, but we can’t modify or reassign them. type keyboard_type = { keys: number; isBackLight: boolean; size: number; }; let keyboard: Readonly<keyboard_type> = { keys: 70, isBackLight: true, size: 20, }; console.log(“Is there backlight in the keyboard? ” + keyboard.isBackLight); console.log(“Total keys in the keyboard are ” + keyboard.keys); // keyboard.size = 30 // this is not allowed as all properties of the keyboard are read-only On compiling, it will generate the following JavaScript code − var keyboard = { keys: 70, isBackLight: true, size: 20 }; console.log(“Is there backlight in the keyboard? ” + keyboard.isBackLight); console.log(“Total keys in the keyboard are ” + keyboard.keys); // keyboard.size = 30 // this is not allowed as all properties of
TypeScript – Template Literal Types ”; Previous Next Template string literals are used to create dynamic strings with variables in JavaScript. Similarly, in TypeScript you can use template literal types to create the dynamic types, which is introduced in the TypeScript 4.1 version. The syntax of the template literal types in TypeScript is very similar to the JavaScript template string literals. Syntax You can follow the syntax below to use the template literal types in TypeScript. type type_name = `some_text ${variable_name}` In the above syntax, ”type_name” is the name of the type. You need to use the backticks (“) to define template literal types. The ”some_text” can be any string value that will remain constant. To add any dynamic value in the type, you need to add the variable name inside the ”${}” structure. Examples Let”s understand the Template Literal Types in details with the help of some examples in TypeScript. Example: Basic Use In the code below, we have defined the ”World” type which contains the “World” as a value. The ”Greeting” type is a template literal type whose value changes based on the value of the ”World” variable. Next, we created the ”greeting” variable of type ”Greeting” which contains a “Hello World” value. If we try to assign another value to it, the TypeScript compiler throws an error. type World = “world”; // Defining a template literal type type Greeting = `Hello, ${World}`; const greeting: Greeting = “Hello, world”; // Correct // const wrongGreeting: Greeting = “Hello, everybody”; // Error: This type is “Hello, world” specifically. console.log(greeting); On compiling, it will generate the following JavaScript code: const greeting = “Hello, world”; // Correct // const wrongGreeting: Greeting = “Hello, everybody”; // Error: This type is “Hello, world” specifically. console.log(greeting); The above example code will produce the following output: Hello, world Example: Combining with Union Types In this code, the ”size” type contains the union of multiple type values. The ”ResponseMessage” type is a template literal type whose value changes based on the value of the ”Size” type. The selectSize() function takes a string of type ”Size” as a parameter, and returns the value of type ”ResponseMessage”. Next, we call the function by passing ”medium” as a function parameter. If we try to pass any other string value than the ”small”, ”medium”, and ”large” as a function parameter, it will throw an error. // Creating a type using literal type type Size = “small” | “medium” | “large”; // Custom template literal type type ResponseMessage = `${Size} size selected`; // Function to select size function selectSize(size: Size): ResponseMessage { return `${size} size selected`; } // Call the function const response: ResponseMessage = selectSize(“medium”); // “medium size selected” console.log(response); On compiling, it will generate the following JavaScript code: // Function to select size function selectSize(size) { return `${size} size selected`; } // Call the function const response = selectSize(“medium”); // “medium size selected” console.log(response); Its output is as follows: medium size selected Example: Conditional String Patterns In this example, we have used the generic types with constraints. Here, ”T extends Status” means, the value of T can be only from the status. The statusMessage type is a combination of the type ”T” and ”status” strings. The printStatus() function takes the type T as a parameter, which can be any one value from the ”Status” type, and returns the value of type ”statusMessage”. Next, we have called the printStatus() function by passing the “loading” value which is a part of the ”Status” type. // Definition of the Status type type Status = “loading” | “success” | “error”; // T can be any of the values in the Status type type StatusMessage<T extends Status> = `${T}Status`; // Function to return a message based on the status function printStatus<T extends Status>(status: T): StatusMessage<T> { return `${status} Status` as StatusMessage<T>; } // Call the function with the “loading” status const loadingMessage = printStatus(“Loading”); // “loadingStatus” console.log(loadingMessage); On compiling, it will generate the following JavaScript code: // Function to return a message based on the status function printStatus(status) { return `${status} Status`; } // Call the function with the “loading” status const loadingMessage = printStatus(“Loading”); // “loadingStatus” console.log(loadingMessage); Its output is as follows: Loading Status Example: API Route Generation The below example demonstrates the real-time practical use of the template literal types. Then, We have defined the Method type which can have any value from the REST API method type. The Entity type defines the entity objects. The getRoute() method takes the entity and method of type Entity and Method, respectively as a parameter. It returns the string value of type APIRoute after combining the entity and method values. // Defining the Method and Entity types type Method = “get” | “post” | “delete”; type Entity = “user” | “post”; // Defining the ApiRoute type type ApiRoute = `/${Entity}/${Method}`; // Defining the getRoute function function getRoute(entity: Entity, method: Method): ApiRoute { return `/${entity}/${method}` as ApiRoute; } // Using the getRoute function const userRoute = getRoute(“user”, “post”); // “/user/post” console.log(userRoute); On compiling, it will generate the following JavaScript code: // Defining the getRoute function function getRoute(entity, method) { return `/${entity}/${method}`; } // Using the getRoute function const userRoute = getRoute(“user”, “post”); // “/user/post” console.log(userRoute); Its output is as follows: /user/post In TypeScript, the template literal type is mainly used when you need to create dynamic types. Print Page Previous Next Advertisements ”;
TypeScript – Creating Types from Types ”; Previous Next TypeScript allows you to create custom types from the existing or built-in types. Creating types from existing types helps you to make code more maintainable and error-resistant. TypeScript is a statically typed language. This means that ideally, each variable, function parameter, and object property should be explicitly assigned a type. Here we will discuss different ways to create custom types from the existing types. Union Types If you want to define a single variable that can store the value of multiple data types, you can use the union operator to combine multiple operators. The union operator is ”|”, and using that you can combine multiple types. Syntax You can follow the syntax below to create custom types by using the union operator. type unionTypes = type1 | type2 | type3 | …; In the above syntax, type1, type2, type3, etc. are data types. Example In the code below, we have defined the ”StringOrNumber” custom type which is a union of the string and number data type. The processValue() function takes the single parameter of the type ”StringOrNumber”. In the function body, we check the type of the parameter using the ”typeof” operator, and based on the string or numeric type, we print the value in the output console. // Defining a union type type StringOrNumber = string | number; // Function that accepts a union type as an argument function processValue(value: StringOrNumber) { // Check if the value is a string or number type if (typeof value === “string”) { console.log(`String: ${value}`); } else { console.log(`Number: ${value}`); } } processValue(“hello”); // Output: String: hello processValue(123); // Output: Number: 123 On compiling, it will generate the following JavaScript code. // Function that accepts a union type as an argument function processValue(value) { // Check if the value is a string or number type if (typeof value === “string”) { console.log(`String: ${value}`); } else { console.log(`Number: ${value}`); } } processValue(“hello”); // Output: String: hello processValue(123); // Output: Number: 123 The output of the above example code is as follows – String: hello Number: 123 Intersection Types The intersection operator (&) allows you to combine the multiple types in the single types. For example, if you have two interfaces or types for Business and contactDetails, and want to combine both types, you can use the intersection operator. Syntax You can follow the syntax below to create custom types by using the intersection operator. type intersectionTypes = type1 & type2 & type3 & …; In the above syntax, we have combined multiple types using the intersection operator. Example In the code below, we have defined the ”Business” interface containing the name and turnover properties. We have also defined the contactDetails interface containing the email and phone properties. After that, we combined both types using the intersection operator and stored them in the ”BusinessContact” type. Next, we have defined the object of the type ”BusinessContact”, and logged it in the console. // Defining a business type interface Business { name: string; turnover: number; } // Defining a contact details type interface ContactDetails { email: string; phone: string; } // Intersection of two types type BusinessContact = Business & ContactDetails; // Creating an object of the type BusinessContact let contact: BusinessContact = { name: “EnviroFront”, turnover: 5000000, email: “[email protected]”, phone: “1234567890” }; console.log(contact); On compiling, it will generate the following JavaScript code. // Creating an object of the type BusinessContact let contact = { name: “EnviroFront”, turnover: 5000000, email: “[email protected]”, phone: “1234567890” }; console.log(contact); The output of the above example code is as follows – { name: ”EnviroFront”, turnover: 5000000, email: ”[email protected]”, phone: ”1234567890” } Utility types TypeScript contains multiple utility types, which makes it easy to transform the particular types and create new types. Let”s look at some of the utility types with examples. Syntax You can follow the syntax below to use any utility type. Utility_type_name<type or interface> In the above syntax, ”utility_type_name” can be replaced with ”Partial”, ”Pick”, ”Record”, etc. based on which utility type you are using. Here, ”type” or ”interface” is the name of the interface from which you want to create a new custom type. Partial Utility Type The partial utility type makes all properties of the interface or type option. So, you can create a new type having all properties optional from the existing type. Example In the code below, we have defined the ”Todo” interface. After that, we used the Partial utility type to create a new type using the Todo interface by making all properties of it optional. Next, we have defined the object of the ”OptionalTodo” type, which contains only the ”title” property, as the ”description” property is optional. // Defining an interface for Todo list interface Todo { title: string; description: string; } // Defining a custom type using the Partial utility type type OptionalTodo = Partial<Todo>; // Creating an object of type OptionalTodo let todo: OptionalTodo = { title: “Buy milk” }; // ”description” is optional console.log(todo); On compiling, it will generate the following JavaScript code. // Creating an object of type OptionalTodo let todo = { title: “Buy milk” }; // ”description” is optional console.log(todo); The output of the above example code is as follows – { title: ”Buy milk” } Pick Utility Type The Pick utility type allows one to pick a subset of properties from the existing types. Let”s understand it via the example below. Example In the code below, we have defined the ”ToDo” interface and used the Pick utility type to create a new type with only the ”title” property from the ”ToDo” interface. Here, the ”ToDoPick” type contains only the ”title” property. // Defining an interface for Todo list interface Todo { title: string; description: string; } // Defining a custom type using the Pick utility type type TodoPick = Pick<Todo, “title”>; let myTodo: TodoPick = { title: “Write a code” }; console.log(myTodo.title); On compiling, it will generate the following JavaScript code. let myTodo =
TypeScript – Type Annotations ”; Previous Next Type Annotations In TypeScript,type annotations offer a way to define (or annotate) the data types of variables, class members, function parameters and return values. TypeScript is a statically typed programming language that optionally supports the dynamic typing. Because of this support any JavaScript file (.js) can be directly renamed as a TypeScript file (.ts). As we know JavaScript is a dynamically typed programming language and TypeScript is the superset of the JavaScript. TypeScript supports all the functionalities of JavaScript plus some additional features. TypeScript provides the way how to annotate the datatype. By the term “type annotations” means assigning the datatypes. Variable Type Annotations TypeScript supports static typing of variables. We can annotate the types of variables while declaring them. Also TypeScript optionally support the dynamic typing as JavaScript. For example, when we define a variable that holds a number, we can define it as follows – var x = 10; The above declaration is absolutely permissible in TypeScript as it supports the dynamic typing. We can annotate the datatype of the variable x as follows – var x: number = 10; To do a type annotation, you can use colon (:) sign after the variable name followed by datatype of the variable. var varName: datatype Followings are the different examples to annotate a variable with different datatypes. let name: string; let age: number; let isEnrolled: boolean; In the example above, we added string as type of variable name. Similarly, age and isEnrolled are annotated with number and boolean type. Example Let”s try the following example. In this example, we have declared two variables, pName, and pAge. We have annotated pName as string and pAge as number. let pName: string; let pAge: number; pName = “John Doe”; pAge = 35; console.log(`Name of the person is ${pName} and his age is ${pAge}`); On compiling, TypeScript compiler will produce the following JavaScript code – let pName; let pAge; pName = “John Doe”; pAge = 35; console.log(`Name of the person is ${pName} and his age is ${pAge}`); The output of the above JavaScript code is as follows – Name of the person is John Doe and his age is 35 Function Type Annotations You can add the type to a function in TypeScript. A function”s type has two parts – the function parameters and the return type of the function. Function Parameter Type Annotation We can annotate the datatypes of the parameters in the function definition. function displayDetails(id: number, name: string){ console.log(“ID:”, id); console.log(“Name”, name); } displayDetails(123,”John”); On compiling, it will produce the following JavaScript code – function displayDetails(id, name) { console.log(“ID:”, id); console.log(“Name:”, name); } displayDetails(123, “John”); The result of the above example code is as follows – ID: 123 Name: John Function Return Type Annotation You can add the datatype of the function return. It will be the datatype of the value returned by the function. function add (x: number, y: number): number { return x + y; } If you are not writing a return type then, the default return type of any function will be undefined. If a function is not returning any value then, you should use void as function return type instead of leaving it off. For example, instead of writing the following – function greet(name: string){ console.log(`Hello Mr. ${name}. Welcome to Tutorials Point.`); } Write the function using void as return type as follows – function greet(name: string): void { console.log(`Hello Mr. ${name}. Welcome to Tutorials Point.`); } Example In the example below, we annotate the function parameters and its return type. The function add take two parameters – x and, y of number type and also a value of number type. The returned value is the sum of the passed arguments to the function. function add(x: number, y: number): number { return x + y; } console.log(add(2,3)) On compiling, it will produce the following JavaScript code – function add(x, y) { return x + y; } console.log(add(2, 3)); The output of the above code is as follows − 5 Object Properties Type Annotations You can use the type annotation to add the types to the properties of an object. Let”s define an object using interface as follows − interface Person { name: string; age: number; } const person: Person = { name: “John Doe”, age: 35, } In the above example, we added types string and number to the properties name and age respectively. You can assign only string value to the name property and similarly only number value to the age property. Suppose if you try to add a string to age, it will throw an error. Type ”string” is not assignable to type ”number”. Example Let”s take a complete example. In this example, we define an interface named Person with two properties – name and age. The name property is annotated as string and age is as number. We create an object named person using the interface Person. Then finally, we display the object properties in the console. interface Person { name: string; age: number; } const person: Person = { name: “John Doe”, age: 35, } console.log(`The person”s name is ${person.name} and person”s age is ${person.age}`); On compiling, it will produce the following JavaScript code − const person = { name: “John Doe”, age: 35, }; console.log(`The person”s name is ${person.name} and person”s age is ${person.age}`); The output of the above example code if as follows − The person”s name is John Doe and person”s age is 35 The type annotations of variables, function parameters and return types, etc. are recommended in TypeScript. But also TypeScript supports dynamic typing as in JavaScript. As you already know that TypeScript supports all ECMAScript features. Print Page Previous Next Advertisements ”;
TypeScript – Classes
TypeScript – Classes ”; Previous Next TypeScript is object oriented JavaScript. TypeScript supports object-oriented programming features like classes, interfaces, etc. A class in terms of OOP is a blueprint for creating objects. A class encapsulates data for the object. Typescript gives built in support for this concept called class. JavaScript ES5 or earlier didn’t support classes. Typescript gets this feature from ES6. Creating classes Use the class keyword to declare a class in TypeScript. The syntax for the same is given below − Syntax class class_name { //class scope } The class keyword is followed by the class name. The rules for identifiers must be considered while naming a class. A class definition can include the following − Fields − A field is any variable declared in a class. Fields represent data pertaining to objects Constructors − Responsible for allocating memory for the objects of the class Functions − Functions represent actions an object can take. They are also at times referred to as methods These components put together are termed as the data members of the class. Consider a class Person in typescript. class Person { } On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var Person = (function () { function Person() { } return Person; }()); Example: Declaring a class class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log(“Engine is : “+this.engine) } } The example declares a class Car. The class has a field named engine. The var keyword is not used while declaring a field. The example above declares a constructor for the class. A constructor is a special function of the class that is responsible for initializing the variables of the class. TypeScript defines a constructor using the constructor keyword. A constructor is a function and hence can be parameterized. The this keyword refers to the current instance of the class. Here, the parameter name and the name of the class’s field are the same. Hence to avoid ambiguity, the class’s field is prefixed with the this keyword. disp() is a simple function definition. Note that the function keyword is not used here. On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log(“Engine is : ” + this.engine); }; return Car; }()); Creating Instance objects To create an instance of the class, use the new keyword followed by the class name. The syntax for the same is given below − Syntax var object_name = new class_name([ arguments ]) The new keyword is responsible for instantiation. The right-hand side of the expression invokes the constructor. The constructor should be passed values if it is parameterized. Example: Instantiating a class var obj = new Car(“Engine 1”) Accessing Attributes and Functions A class’s attributes and functions can be accessed through the object. Use the ‘ . ’ dot notation (called as the period) to access the data members of a class. //accessing an attribute obj.field_name //accessing a function obj.function_name() Example: Putting them together class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log(“Function displays Engine is : “+this.engine) } } //create an object var obj = new Car(“XXSY1”) //access the field console.log(“Reading attribute value Engine as : “+obj.engine) //access the function obj.disp() On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log(“Function displays Engine is : ” + this.engine); }; return Car; }()); //create an object var obj = new Car(“XXSY1”); //access the field console.log(“Reading attribute value Engine as : ” + obj.engine); //access the function obj.disp(); The output of the above code is as follows − Reading attribute value Engine as : XXSY1 Function displays Engine is : XXSY1 Class Inheritance TypeScript supports the concept of Inheritance. Inheritance is the ability of a program to create new classes from an existing class. The class that is extended to create newer classes is called the parent class/super class. The newly created classes are called the child/sub classes. A class inherits from another class using the ‘extends’ keyword. Child classes inherit all properties and methods except private members and constructors from the parent class. Syntax class child_class_name extends parent_class_name However, TypeScript doesn’t support multiple inheritance. Example: Class Inheritance class Shape { Area:number constructor(a:number) { this.Area = a } } class Circle extends Shape { disp():void { console.log(“Area of the circle: “+this.Area) } } var obj = new Circle(223); obj.disp() On compiling, it will generate following JavaScript code. //Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var Shape = (function () { function Shape(a) { this.Area = a; } return Shape; }()); var Circle = (function (_super) { __extends(Circle, _super); function Circle() { _super.apply(this, arguments); } Circle.prototype.disp = function () { console.log(“Area of the circle: ” + this.Area); }; return Circle; }(Shape)); var obj = new Circle(223); obj.disp(); The output of the above code is as follows − Area of the Circle: 223 The above example declares a class Shape. The class is extended by the Circle class. Since there is an inheritance relationship between the classes, the child class i.e. the class Car gets an implicit access to its parent class attribute i.e. area. Inheritance can be classified as − Single − Every class can at the most extend from one parent class Multiple − A class can inherit from multiple classes. TypeScript doesn’t support multiple inheritance. Multi-level − The following example shows how multi-level inheritance works. Example class Root { str:string; } class Child extends Root {} class Leaf extends Child {}
TypeScript – Intersection Types ”; Previous Next 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. type intersepted_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. interface Book { book_id: number book_name: string } interface Author { author_id: number author_name: string } type intersected_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. interface Student { student_id: number student_name: string } interface Class { class_id: number class_name: string } interface Subject { subject_id: number subject_name: string } type intersected_type_1 = (Student & Class) & Subject type intersected_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. Print Page Previous Next Advertisements ”;
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
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