TypeScript Note ✍🏻
🧑🏻‍💻

TypeScript Note ✍🏻

📌 What is TypeScript?

  • TS is not a new programming language
  • TypeScript is a typed superset of JavaScript.
  • Developed by Microsoft.
  • Object oriented

📌 Benefits of TypeScript

  • Easy Code Management
  • Support ECMAscrpt
  • We can use data type, classed, interface etc
  • IDE support

📌 Typescript run env


  1. Install node.js
  1. npm i -g typescript

📌 How to run Typescript code


  1. Make app.ts file
  1. then run command tsc app.ts
  1. This create new file app.js
  1. To run run in
    1. Browser : link app.js to index.html to run in browser using script tag.
    2. Terminal : node app.js
  1. This command tsc app.js need to be done again and again on every change in TS file. To avoid this, use command : tsc app.ts --watch
  1. Output
Typescript
notion image
JavaScripts
notion image

📌 Types in TypeScript


The primitives:stringnumber, andboolean

Type
Predicate
string
typeof s === "string"
number
typeof n === "number"
Boolean
typeof b === "boolean"
undefined
typeof undefined === "undefined"
function
typeof f === "function"
array
Array.isArray(a)
 
  • Defining type of variable in typescript is optional.
notion image
 
  • After defining type, data stored must be as per type defined
notion image
 
💡
Read Here all data types
 

📌 Type Inference

In TypeScript, there are several places where type inference is used to provide type information when there is no explicit type annotation. For example, in this code
notion image
More Example
notion image
 
notion image
 

📌 Array in TypeScript


  • Defining array: here ts take array default type as String
notion image
 
  • Here Ts has take array type as string so giving error in pushing 10 numeric value
notion image
 
  • Here while defining array we define array as mix of string and Number
notion image
 
  • Arrays is consider to be mix of String and Number, Inserting Boolean give error
notion image
Note : TS check type of value which can be inserted in array
 
  • Defining data type at the time of declaration
let data:string[] = ["anil","abhishek","naman"]; let data:(string | number)[] = [19103056,"abhishek","tiwari"]
 

More on Array:

1. Array Destructuring: Array destructuring is a way to unpack values from an array and assign them to variables. Here's an example: const [first, second] = [1, 2]; console.log(first); // Output: 1 console.log(second); // Output: 2 2. Object Destructuring: Object destructuring is a way to unpack values from an object and assign them to variables. Here's an example: const {name, age} = {name: 'John', age: 30}; console.log(name); // Output: 'John' console.log(age); // Output: 30 3. Mixed Destructuring: You can also use mixed destructuring to unpack values from arrays and objects in a single statement. Here's an example: const {name, age, skills: [skill1, skill2]} = {name: 'John', age: 30, skills: ['JavaScript', 'TypeScript']}; console.log(name); // Output: 'John' console.log(age); // Output: 30 console.log(skill1); // Output: 'JavaScript' console.log(skill2); // Output: 'TypeScript' 4. Property renaming: You can rename the property while destructuring an object. Here's an example: const {name: fullName, age} = {name: 'John', age: 30}; console.log(fullName); // Output: 'John' console.log(age); // Output: 30 5. Default Values: You can provide default values while destructuring an array or object. Here's an example: const [first = 1, second = 2] = []; console.log(first); // Output: 1 console.log(second); // Output: 2 const {name = 'John', age = 30} = {}; console.log(name); // Output: 'John' console.log(age); // Output: 30 6. Spreads: You can use spreads to copy the elements from an array into another array or to merge two objects into one. Here's an example: const arr1 = [1, 2]; const arr2 = [3, 4]; const arr3 = [...arr1, ...arr2]; console.log(arr3); // Output: [1, 2, 3, 4] const obj1 = {name: 'John'}; const obj2 = {age: 30}; const obj3 = {...obj1, ...obj2}; console.log(obj3); // Output: {name: 'John', age: 30}

📌 Object


notion image
  1. Here while assigning values to key , TS set value data type as key data type
  1. Updating : So here reassigning user.name = 200 give error , as type of name set to String, similar age type set to Number and address type String
  1. Adding new Value : We cannot add new key in object
    1. user.email = “peter@gmail.com” Show Error
 

Defining Type of key using Interface / Custom type

  • Setting key types using interface
notion image
 

Any KeyWord

  • Using Interface set key type to Any
  • Here address : any means we can assign string , number , or any other data type
notion image
 

Setting Object Type to Any

  • Now we can assign any type of value to any key
  • Imp : we can also add new key if using any
    • users.email = “abhishek@gmail.com”
notion image

📌 Union


  • A union type describes a value that can be one of several types.
  • We use the vertical bar ( | ) to separate each type, so number | string | boolean is the type of a value that can be a number , a string , or a boolean .
notion image
 
With function parameters
notion image

📌 Interface in TypeScript


Interfaces are capable of describing the wide range of shapes that JavaScript objects can take.
notion image
 
  • Making object from Interface
notion image
Calling method on UserType instance: users.getName()
 
Example of using interface with Function, parameter
  • Argument : object name pt and type Point
notion image
 
  • Making parameter “b” optional
notion image
 

Optional Properties

interface PaintOptions { shape: Shape; xPos?: number; yPos?: number; } function paintShape(opts: PaintOptions) { // ... } const shape = getShape(); paintShape({ shape }); paintShape({ shape, xPos: 100 }); paintShape({ shape, yPos: 100 }); paintShape({ shape, xPos: 100, yPos: 100 });
 

Intersection Types

interface Colorful { color: string; } interface Circle { radius: number; } type ColorfulCircle = Colorful & Circle;
Here, we’ve intersected Colorful and Circle to produce a new type that has all the members of Colorful and Circle.
function draw(circle: Colorful & Circle) { console.log(`Color was ${circle.color}`); console.log(`Radius was ${circle.radius}`); } // okay draw({ color: "blue", radius: 42 }); // oops, draw({ color: "red", raidus: 42 }); // property : raidus doesn't exists

📌 Class In TypeScript


✏️ Defining Class

notion image
notion image
 

✏️ Defining data types of class , initialising by constructor

notion image
 

✏️ Data types of Class , with default value

notion image
 

Doing constructor overloading

  • And this is a more complex example with three constructor overloads:
class Product { name: string; price: number; constructor(name: string, price: number); constructor(name: string); constructor(); constructor() { if (arguments.length === 2) { this.name = arguments[0]; this.price = arguments[1]; } else if (arguments.length === 1) { this.name = arguments[0]; this.price = 0; } else { this.name = ""; this.price = 0; } } } const product1 = new Product("Table", 100); const product2 = new Product("Chair"); const product3 = new Product();
Here we cannot have multiple constructor Implementations.
 
Constructor and Shorthand initialization
class Animal { constructor(public species: string, public name: string) {} getDetails() { return `This is a ${this.species} named ${this.name}.`; } } const dog = new Animal("dog", "Buddy"); console.log(dog.getDetails()); // Output: This is a dog named Buddy.

Class : private and readonly

privatemembers can only be accessed within the class that defines them, and not from outside the class. This means that private members cannot be accessed by other code, including code that extends the class. Here's an example:
 
class Example { private privateProperty: string = "Private"; public publicProperty: string = "Public"; private privateMethod() { console.log("This is a private method."); } public publicMethod() { console.log("This is a public method."); this.privateMethod(); // Private method can be called within the class. } } const example = new Example(); console.log(example.publicProperty); // Output: Public console.log(example.privateProperty); // Error: Property 'privateProperty' is private and only accessible within class 'Example'. example.privateMethod(); // Error: Property 'privateMethod' is private and only accessible within class 'Example'. example.publicMethod(); // Output: This is a public method. This is a private method.
 
readonly members, on the other hand, can be accessed from outside the class, but cannot be modified once they are initialized. This means that readonly members can be used to define properties that can be read but not changed. Here's an example:
class Example { readonly readonlyProperty: string = "Readonly"; public publicProperty: string = "Public"; constructor() { this.readonlyProperty = "Updated"; // Error: Cannot re-assign to 'readonlyProperty' because it is already assigned. } } const example = new Example(); console.log(example.publicProperty); // Output: Public console.log(example.readonlyProperty); // Output: Readonly
More example
class Employee { readonly empCode: number; empName: string; constructor(code: number, name: string) { this.empCode = code; this.empName = name; } } let emp = new Employee(10, "John"); emp.empCode = 20; //Compiler Error emp.empName = 'Bill';
 

Static properties

class Employee { static headcount: number = 0; constructor( private firstName: string, private lastName: string, private jobTitle: string) { Employee.headcount++; } }
 
let john = new Employee('John', 'Doe', 'Front-end Developer'); let jane = new Employee('Jane', 'Doe', 'Back-end Developer'); console.log(Employee.headcount); // 2
 
Similar to the static property, a static method is also shared across instances of the class.
class Employee { private static headcount: number = 0; constructor( private firstName: string, private lastName: string, private jobTitle: string) { Employee.headcount++; } public static getHeadcount() { return Employee.headcount; } } // To call a static method, you use the className.staticMethod() syntax. For example: console.log(Employee.getHeadcount()); // 2
 

📌 TypeScript Inheritance


Inheritance Example

notion image
 
Super Keyword
notion image
 

✔️ Implementing Interface and its function

interface IDeveloper { name: string position: string develop: () => void } class Developer implements IDeveloper { name: string; position: string; constructor(name: string, position: string) { this.name = name; this.position = position; } develop(): void { console.log('develop an app'); } }

📌 TypeScript Module


The variables, functions, classes, and interfaces declared in a module cannot be accessible outside the module directly. We can create a module by using the export
 keyword and can use in other modules by using the import
 keyword.
The variables, functions, classes, and interfaces declared in a module cannot be accessible outside the module directly. We can create a module by using the export  keyword and can use in other modules by using the import  keyword.

Import Syntax

Import { export name } from "file path without extension"
 
export let age : number = 20; export class Employee { empCode: number; empName: string; constructor(name: string, code: number) { this.empName = name; this.empCode = code; } displayEmployee() { console.log ("Employee Code: " + this.empCode + ", Employee Name: " + this.empName ); } } let companyName:string = "XYZ";
Employee.ts
 
Importing a Single export from a Module:
import { Employee } from "./Employee"; let empObj = new Employee("Steve Jobs", 1); empObj.displayEmployee(); //Output: Employee Code: 1, Employee Name: Steve Jobs
EmployeeProcessor.ts
 
Importing Module into Variable
import * as Emp from "./Employee" console.log(Emp.age); // 20 let empObj = new Emp.Employee("Bill Gates" , 2); empObj.displayEmployee(); //Output: Employee Code: 2, Employee Name: Bill Gates
EmployeeProcessor.ts
 
Renaming Export Module
import { Employee as Associate } from "./Employee" let obj = new Associate("James Bond" , 3); obj.displayEmployee();//Output: Employee Code: 3, Employee Name: James Bond
EmployeeProcessor.ts
 
More Example :
notion image
 

📌 TypeScript - Generics


Generics offer a way to create reusable components. Generics provide a way to make components work with any data type and not restrict to one data type. So, components can be called or used with a variety of data types.
Generics offer a way to create reusable components. Generics provide a way to make components work with any data type and not restrict to one data type. So, components can be called or used with a variety of data types.
 
function print<T>(items : T ) : void { console.log(items) } print<number[]>([100, 200, 300]); print<string[]>(["Abhishek", "Tiwari","12"]) print<Object>({fname:"Abhishek",lname:"Tiwari",age:12})

Output

[100, 200, 300]

["Abhishek", "Tiwari", "12"]

{ "fname": "Abhishek", "lname": "Tiwari", "age": 12 }
 

Generic function without specifying the type variable

  • It is not recommended but we can also call a generic function without specifying the type variable.
  • The compiler will use type inference to set the value of T on the function based on the data type of argument values.
let myNumArr = getArray([100, 200, 300]); // OK
 
More Example:
Here function can only return Array of type T
function getArray<T>(items : T[] ) : T[] { return new Array<T>().concat(items); } let myNumArr = getArray<number>([100, 200, 300]);

Generic Constraints

The display function is a generic function with constraints. A constraint is specified after the generic type in the angle brackets. The constraint <T extends Person> specifies that the generic type T must extend the class Person.
class Person { firstName: string; lastName: string; constructor(fname:string, lname:string) { this.firstName = fname; this.lastName = lname; } } function display<T extends Person>(per: T): void { console.log(`${ per.firstName} ${per.lastName}` ); } var per = new Person("Bill", "Gates"); display(per); //Output: Bill Gates display("Bill Gates");//Compiler Error

Generic Classes

class KeyValuePair<T,U> { private key: T; private val: U; setKeyValue(key: T, val: U): void { this.key = key; this.val = val; } display():void { console.log(`Key = ${this.key}, val = ${this.val}`); } } let kvp1 = new KeyValuePair<number, string>(); kvp1.setKeyValue(1, "Steve"); kvp1.display(); //Output: Key = 1, Val = Steve let kvp2 = new KayValuePair<string, string>(); kvp2.SetKeyValue("CEO", "Bill"); kvp2.display(); //Output: Key = CEO, Val = Bill

Generic Class implements Generic Interface

interface IKeyValueProcessor<T, U> { process(key: T, val: U): void; }; class kvProcessor<T, U> implements IKeyValueProcessor<T, U> { process(key:T, val:U):void { console.log(`Key = ${key}, val = ${val}`); } } let proc: IKeyValueProcessor<number, string> = new kvProcessor(); proc.process(1, 'Bill'); //Output: key = 1, value = Bill

📌 TypeScript Data Type - Enum


Enums allow us to declare a set of named constants i.e. a collection of related values that can be numeric or string values
Enums allow us to declare a set of named constants i.e. a collection of related values that can be numeric or string values
 
  • Defining Enum
    • enum PrintMedia { Newspaper, Newsletter, Magazine, Book }
Here, enum values start from zero and increment by 1 for each member. It would be represented as:
Newspaper = 0 Newsletter = 1 Magazine = 2 Book = 3
🔴 Error: enum variable can take only value defined in enum
let media : PrintMedia = "apple" ;
⚠️ Error: Type '"apple"' is not assignable to type 'PrintMedia'.
 
  • We also have the option to initialise the first numeric value ourselves. For example, we can write the same enum as:
    • enum PrintMedia { Newspaper = 1, Newsletter, Magazine, Book }
 
  • It is not necessary to assign sequential values to Enum members. They can have any values.
    • enum PrintMedia { Newspaper = 1, Newsletter = 5, Magazine = 5, Book = "not available" }

      Computed Enums:

      enum PrintMedia { Newspaper = 1, Newsletter, Magazine, Book } function getMedia(mediaName: string): PrintMedia { if ( mediaName === 'Forbes' || mediaName === 'Outlook') { return PrintMedia.Magazine; } } let mediaType: PrintMedia = getMedia('Forbes'); // returns Magazine PrintMedia.Newsetter; // returns 5
       

      📌 Symbols


      Starting with ECMAScript 2015, symbol is a primitive data type, just like number and string.
      symbol values are created by calling the Symbol constructor.
       
      let sym1 = Symbol(); let sym2 = Symbol("key"); // optional string key ----------------------------------------------------- let sym2 = Symbol("key"); let sym3 = Symbol("key"); sym2 === sym3; // false, symbols are unique
       
      Symbols can be used as keys for object properties.
      const sym = Symbol(); let obj = { [sym]: "value", }; console.log(obj[sym]); // "value"
       
      Defining Function
      const demoFunction = Symbol(); class C { [demoFunction] { return "Working Function"; } } let c = new C(); let className = c[demoFunction](); // "Working Function"

      📌 tsconfig file


       
      notion image
       
    • The field in outDir indicates - output files of tsc compiler .
    • The field rootDir indicates - src folder of which files will be compiled .
    •  
      notion image
       
      Issue when dummy.ts is present in root folder , tsc put src folder(inside which app.js and user.js) and dummy.js in public folder. This disturbed the whole structure.
      notion image

      Handling this Issue

      #Include -include

      Specifies an array of filenames or patterns to include in the program. These filenames are resolved relative to the directory containing the tsconfig.json file.
      { "include": ["src/**/*", "tests/**/*"], "exclude": ["node_modules", "**/*.spec.ts"] // Specifies an array of filenames or patterns that should be skipped when resolving include. }
      Which would include: (example )
      . ├── scripts ⨯ │ ├── lint.ts ⨯ │ ├── update_deps.ts ⨯ │ └── utils.ts ⨯ ├── src ✓ │ ├── client ✓ │ │ ├── index.ts ✓ │ │ └── utils.ts ✓ │ ├── server ✓ │ │ └── index.ts ✓ ├── tests ✓ │ ├── app.test.ts ✓ │ ├── utils.ts ✓ │ └── tests.d.ts ✓ ├── package.json ├── tsconfig.json └── yarn.lock
      include and exclude support wildcard characters to make glob patterns:
    • * matches zero or more characters (excluding directory separators)
    • ? matches any one character (excluding directory separators)
    • **/ matches any directory nested to any level
    •  

      📌 TypeScript - Tuples


    • Tuple vs Other Data Types
    • var empId: number = 1; var empName: string = "Steve"; // Tuple type variable var employee: [number, string] = [1, "Steve"];
       
    • A tuple type variable can include multiple data types as shown below.
    • var employee: [number, string] = [1, "Steve"]; var person: [number, string, boolean] = [1, "Steve", true]; var user: [number, string, boolean, number, string];// declare tuple variable user = [1, "Steve", true, 20, "Admin"];// initialize tuple variable
       
    • Accessing Tuple Elements
    • var employee: [number, string] = [1, "Steve"]; employee[0]; // returns 1 employee[1]; // returns "Steve"
       
    • Add Elements into Tuple
    • var employee: [number, string] = [1, "Steve"]; employee.push(2, "Bill"); employee.push(3); console.log(employee); // output : [1, "Steve", 2, "Bill", 3]
       
    • Making insertion of other value optional
    • //Here boolean value is optional var employee: [number, string,boolean?] = [1, "Steve"]; employee.push(2, "Bill"); employee.push("naman"); employee.push(5) employee.push(true) console.log(employee); //Output: [1, "Steve", 2, "Bill", "naman", 5, true]

      📌 Literals in TypeScript


      Apply values rather than apply types to a variable or parameter
      let data :"abc"|12 = 12;
      either "abc" or 12 can be assigned to data.
       

      Type Alias :

      type Easing = "ease-in" | "ease-out" | "ease-in-out"; class UIElement { animate(dx: number, dy: number, easing: Easing) { if (easing === "ease-in") { // ... } else if (easing === "ease-out") { } else if (easing === "ease-in-out") { } else { // It's possible that someone could reach this // by ignoring your types though. } } } let button = new UIElement(); button.animate(0, 0, "ease-in"); button.animate(0, 0, "uneasy");
       ❌ Argument of type '"uneasy"' is not assignable to parameter of type 'Easing'.
       

      📌 TypeScript void type

      The void type denotes the absence of having any type at all. It is a little like the opposite of the any type.
      Typically, you use the void type as the return type of functions that do not return a value.
      For example:
      function log(message): void { console.log(messsage); }
      • Use the void type as the return type of functions that do not return any value.
       

      📌 TypeScript “never” type

      The never type represents values which are never observed.
      In a return type, this means that the function throws an exception or terminates execution of the program.
       
      function fail(msg: string): never { thro
       

      ⭐ Question : Important

      explain this code: let data:any; data =10; let item:string="a"; console.log(typeof item) // string item = data; console.log(typeof item) // number
       
      1. code declares a variable data and initializes it with a value of type any. The any type means that data can hold any value, regardless of its type.
      1. Next, the code assigns the value 10 to data, which TypeScript allows because data is of type any.
      1. Then, the code declares a variable item of type string and initializes it with the value "a".
      1. The code then logs the type of item to the console using the typeof operator. Since item is declared as a string, the output will be "string".
      1. Finally, the code assigns the value of data to item. Since data is of type any, TypeScript allows this assignment even though item is of type string.
      The code then logs the type of item to the console again using the typeof operator. This time, the output will be "number", because item now holds the value 10, which is a number.
       

      why ? The code assigns the value of data to item. data is of type any, TypeScript allows this assignment even though item is of type string.

       
      TypeScript allows the assignment of data (of type any) to item (of type string) because any is the most permissive type in TypeScript.
      When a variable is declared as any, TypeScript essentially turns off its type checking for that variable, allowing any value to be assigned to it and any operation to be
      performed on it.
      This means that when data is assigned the value 10, its type is set to number. Later on, when data is assigned to item, TypeScript doesn't raise an error because any allows any value to be assigned to it. However, when the typeof operator is used on item, it correctly outputs "number" because item now holds the value 10.
      Note : While using any can be convenient at times, it can also lead to errors and bugs in your code. It's generally recommended to avoid using any when possible, and to use more specific types instead to help catch errors at compile-time rather than at runtime.
       

      📌  unknown Type in TS


       
      let data:unknown; data = 20; data="test data"; let item:string = "Abhishek"; item = data // error , but not in case of any
      Error : Type 'unknown' is not assignable to type 'string'.
       
      How to assign data variable string into item .
      let data:unknown; data = 20; data="test data"; let item:string = "Abhishek"; if(typeof data === 'string'){ // after type checking we can assign item = data }
       

      📌 any V/S unknown

    • unknown is a type in TypeScript that's like a more careful version of any.
    • With any, you can do pretty much anything you want with a value, but with unknown, TypeScript makes you be more careful.
    • You can't use an unknownvalue until you've checked what type it is, and you need to tell TypeScript what the type is before you can use it. It's like making sure you know what something is before you can use it, instead of just assuming it's okay to use without checking.
    •  
       

      📌 DOM Manipulation In TypeScript

       

      More Topic :

      Type casting
      let input = document.querySelector('input') as HTMLInputElement; let inputValue = input.value; let text:unknown = "string"; let value = (text as string).length;
       
       
       
       
Built with Potion.so