{"id":28372657,"url":"https://github.com/sk-azraf-sami/learn-typescript","last_synced_at":"2026-04-28T17:34:00.786Z","repository":{"id":293852609,"uuid":"981545712","full_name":"Sk-Azraf-Sami/Learn-Typescript","owner":"Sk-Azraf-Sami","description":"I made this note by following the tutorial of 'Dave Gray' on YouTube and also took help from chatgpt to make it more organize and readable. ","archived":false,"fork":false,"pushed_at":"2025-05-20T11:08:14.000Z","size":265,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-24T18:48:24.637Z","etag":null,"topics":["documentation","javascript","note","notes","type-safe","type-safety","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sk-Azraf-Sami.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-11T11:04:44.000Z","updated_at":"2025-05-20T11:08:17.000Z","dependencies_parsed_at":"2025-05-17T15:20:00.804Z","dependency_job_id":"5d1a192c-d81c-4bb1-8d14-1330dc2b927b","html_url":"https://github.com/Sk-Azraf-Sami/Learn-Typescript","commit_stats":null,"previous_names":["sk-azraf-sami/learn-typescript"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Sk-Azraf-Sami/Learn-Typescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sk-Azraf-Sami%2FLearn-Typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sk-Azraf-Sami%2FLearn-Typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sk-Azraf-Sami%2FLearn-Typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sk-Azraf-Sami%2FLearn-Typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sk-Azraf-Sami","download_url":"https://codeload.github.com/Sk-Azraf-Sami/Learn-Typescript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sk-Azraf-Sami%2FLearn-Typescript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32392298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["documentation","javascript","note","notes","type-safe","type-safety","typescript"],"created_at":"2025-05-29T16:15:30.468Z","updated_at":"2026-04-28T17:34:00.755Z","avatar_url":"https://github.com/Sk-Azraf-Sami.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Table of Contents \n- [Basic Concepts \u0026 Types](#basic-concepts--types)\n- [Arrays, Tuples, and Type Safety](#arrays-tuples-and-type-safety)\n- [Object](#object)\n- [Advanced Types \u0026 Functions](#advanced-types--functions)\n- [Type Assertions, Unknown, and DOM Handling](#type-assertions-unknown-and-dom-handling)\n- [OOP, Interfaces, Index Signatures, and Records](#oop-interfaces-index-signatures-and-records)\n- [Generics](#generics)\n- [Utility Types](#utility-types)\n\n---\n\n## [Basic Concepts \u0026 Types](#basic-concepts--types)\n\n### ✅ 1. Variable Declaration with Type Inference\n\n```ts\nlet username = 'Sami';\nconsole.log(username);\n```\n\n* TypeScript automatically infers the type of `username` as `string` because it's initialized with a string.\n* This is called **type inference** — TypeScript assigns a type based on the value provided.\n\n---\n\n### 🔢 2. Explicit Type Annotation\n\n```ts\nlet a: number = 12;\n// let b: string = \"6\";\nlet b: number = 6;\nlet c: number = 10;\n\nconsole.log(a / b);\n```\n\n* You can explicitly define the type of a variable using `: type`.\n* Here, `a`, `b`, and `c` are explicitly set to type `number`.\n* TypeScript will throw an error if you try to assign a value of a different type (e.g., uncommenting `b: string = \"6\"`).\n\n---\n\n### 👤 3. Type Safety\n\n```ts\nlet myname = 'azraf';\n// myname = 83;\n```\n\n* TypeScript infers `myname` as `string`.\n* If you try to assign a number to `myname`, it results in a **type error**.\n* This enforces **type safety** — helps prevent bugs caused by unexpected types.\n\n---\n\n### ➕ 4. Function with Type Annotations\n\n```ts\nconst sum = (a: number, b: number) =\u003e {\n    return a + b;\n};\n```\n\n* Function parameters and return values can have types.\n* This ensures correct usage and avoids type-related issues in function calls.\n\n---\n\n### 🔄 5. The `any` Type\n\n```ts\nlet album: any;\n```\n\n* The `any` type disables type checking for that variable.\n* It can hold **any value**, such as string, number, object, etc.\n* Use with caution — it sacrifices TypeScript’s benefits.\n\n---\n\n### 🔁 6. Union Types\n\n```ts\nlet postId: string | number;\n```\n\n* A **union type** allows a variable to be one of multiple types.\n* `postId` can be either a `string` or a `number`.\n\n---\n\n### 🔤 7. Regular Expressions\n\n```ts\nlet re: RegExp = /\\w+/g;\n```\n\n* `RegExp` is a built-in type in TypeScript for regular expressions.\n* `\\w+` matches one or more word characters.\n* The `g` flag stands for \"global\" (matches all occurrences).\n\n---\n\n## [Arrays, Tuples, and Type Safety](#arrays-tuples-and-type-safety)\n\n### 📚 1. String Array\n\n```ts\nlet stringArr = ['Dhaka', 'Bangladesh', 'Khulna'];\n```\n\n* TypeScript infers `stringArr` as `string[]`.\n* All elements must be of type `string`.\n\n```ts\n// stringArr[0] = 115; ❌ Error\n```\n\n* You cannot assign a `number` to an index of a `string[]` array.\n\n---\n\n### 🔄 2. Mixed Type Array (Union Inference)\n\n```ts\nlet mixArr = ['ntm', 83, 'sas', 115];\n```\n\n* TypeScript infers this as `(string | number)[]` — a union of `string` and `number`.\n\n```ts\nmixArr[0] = 1907; // ✅ OK\n// mixArr.unshift(true); ❌ Error\n```\n\n* You can reassign elements with either `string` or `number`.\n* Adding a `boolean` (`true`) causes a type error, as `boolean` isn’t in the union.\n\n---\n\n### ⚠️ 3. Array Type Compatibility\n\n```ts\n// stringArr = mixArr; ❌ Error\nmixArr = stringArr; // ✅ OK\n```\n\n* You **cannot assign** a union-typed array (with more types) to a strictly typed one (`string[]`).\n* But assigning a `string[]` to a `(string | number)[]` is allowed — it's compatible because `string[]` is a subset of the union.\n\n---\n\n### 🏷️ 4. Explicit Array Typing\n\n```ts\nlet stuName: string[] = [];\nstuName.push('ntm');\n```\n\n* You can explicitly declare an array’s type using `type[]`.\n* Here, only strings can be added to `stuName`.\n\n---\n\n### 📦 5. Tuples – Fixed-Length \u0026 Fixed-Type Arrays\n\n```ts\nlet myTuples: [string, number, boolean] = ['ntm', 83, true];\n```\n\n* A **tuple** defines:\n\n  * A fixed number of elements.\n  * Each element must be of a specific type **and position matters**.\n\n```ts\nlet arrTest = ['ntm', 83, true];\narrTest = myTuples; // ✅ OK (tuple → array)\nmyTuples = arrTest; // ❌ Error (array → tuple)\n```\n\n* You can assign a tuple to a normal array.\n* But you **can’t assign** a regular array to a tuple unless its exact structure and types are guaranteed.\n\n---\n\nGreat work! Here's the next part of your **TypeScript Notes**, now covering **Type Aliases**, **Function Types**, **Interfaces**, **Optional \u0026 Default Parameters**, **Rest Parameters**, and **the `never` Type** — with well-structured explanations.\n\n---\n\n## [Object](#object)\n\n\n### 🔹 Arrays Are Objects\n\n```ts\nlet myObj: object; \nmyObj = []; // Valid: arrays are a type of object\nmyObj = {}; // Valid: plain object\nconsole.log(typeof myObj); // 'object'\n```\n\n#### 💡 Explanation:\n\n* In TypeScript (and JavaScript), arrays are technically objects.\n* You can assign both arrays and plain objects to a variable of type `object`.\n\n---\n\n### 🔹 Working with Object Types\n\n#### Defining and Using Object Type\n\n```ts\ntype Guitarist = {\n  name: string;\n  active: boolean;\n  album: (string | number)[];\n};\n\nlet evh: Guitarist = {\n  name: 'Test',\n  active: false,\n  album: ['ntm', 115]\n};\n\nlet jp: Guitarist = {\n  name: 'Test',\n  active: false,\n  album: ['ntm', 'sas', 115, 83]\n};\n\nevh = jp; // Valid assignment\n```\n\n#### 💡 Explanation:\n\n* `type` lets you define custom object types.\n* Here, `album` accepts an array of `string | number`.\n\n---\n\n### 🔹 Optional Object Properties\n\n```ts\ntype GuitaristOpt = {\n  name: string;\n  active?: boolean; // Optional property\n  album: (string | number)[];\n};\n\nlet evhOpt: GuitaristOpt = {\n  name: 'Test',\n  active: false,\n  album: ['ntm', 115]\n};\n\nlet jpOpt: GuitaristOpt = {\n  name: 'Test',\n  album: ['ntm', 'sas', 115, 83]\n};\n\nevhOpt = jpOpt; // Valid: 'active' is optional\n```\n\n#### 💡 Explanation:\n\n* Optional properties (using `?`) allow you to omit them when creating objects.\n\n---\n\n### 🔹 Using Object Types in Functions\n\n```ts\nconst greetGuitarist = (guitarist: Guitarist) =\u003e {\n  return `Hello ${guitarist.name}!`;\n};\n```\n\n#### 💡 Explanation:\n\n* You can pass a custom object type into a function parameter.\n* TypeScript ensures the object matches the type structure.\n\n---\n\n### 🔹 Type vs Interface\n\n```ts\ntype GuitaristTest = {\n  name: string;\n  active?: boolean;\n  album: (string | number)[];\n};\n\ninterface GuitaristTest2 {\n  name: string;\n  active?: boolean;\n  album: (string | number)[];\n}\n```\n\n#### 💡 Explanation:\n\n* `type` and `interface` are mostly interchangeable for object shapes.\n* Interfaces are preferred in large-scale OOP or when extending.\n\n---\n\n### 🔹 Optional Chaining in Functions\n\n```ts\ninterface Student {\n  name?: string;\n  roll: number;\n}\n\nconst stu1: Student = { name: 'ntm', roll: 83 };\nconst stu2: Student = { roll: 115 };\n\nconst greetStudent = (student: Student) =\u003e {\n  return `Hello ${student.name?.toUpperCase()}`;\n  // Or with narrowing:\n  // if (student.name) {\n  //   return `Hello ${student.name.toUpperCase()}`;\n  // }\n  // return `Hello`;\n};\n\nconsole.log(greetStudent(stu1)); // Hello NTM\nconsole.log(greetStudent(stu2)); // Hello undefined\n```\n\n#### 💡 Explanation:\n\n* Use optional chaining (`?.`) to safely access potentially undefined properties.\n* Alternative: use conditional checks (narrowing).\n\n---\n\n### 🔹 Enums in TypeScript\n\n```ts\nenum Grade {\n  A = 83,\n  B, // 84\n  C  // 85\n}\n\nconsole.log(Grade.B); // 84\n```\n\n#### 💡 Explanation:\n\n* Enums allow for named constants.\n* If one member is initialized (`A = 83`), others increment by 1 automatically unless explicitly set.\n\n---\n\n\n## [Advanced Types \u0026 Functions](#advanced-types--functions)\n\n### 📌 1. Type Aliases\n\n```ts\ntype stringOrNumber = string | number;\ntype stringOrNumberArray = string | number[];\n```\n\n* **Type aliases** help you create custom names for union types or complex types.\n* Useful for cleaner and more readable code.\n\n---\n\n### 👥 2. Custom Object Types\n\n```ts\ntype Member = {\n  ID: stringOrNumber;\n  Name: string;\n  Experience: stringOrNumberArray;\n};\n```\n\n* The `Member` type uses other custom type aliases.\n* Great for defining consistent structure across multiple objects.\n\n---\n\n### 🧱 3. Literal Types\n\n```ts\nlet myName = 'sami';\n\nlet userName: 'ntm' | 'sas';\nuserName = 'ntm'; // ✅ Allowed\n```\n\n* A **literal type** restricts a variable to exactly one or more allowed values.\n* Acts like an enum without extra syntax.\n\n---\n\n### 🔧 4. Functions with Type Annotations\n\n#### Basic Functions\n\n```ts\nconst add = (a: number, b: number): number =\u003e a + b;\n\nconst logMsg = (message: any): void =\u003e {\n  console.log(message);\n};\n```\n\n* `:number` specifies return type.\n* `:void` indicates the function **does not return a value**.\n\n---\n\n#### Function Expressions\n\n```ts\nlet subtract = function(num1: number, num2: number): number {\n  return num1 - num2;\n};\n```\n\n* Function expressions can also have type annotations.\n\n---\n\n### 🧾 5. Function Type Aliases \u0026 Interfaces\n\n```ts\ntype mathFunction = (a: number, b: number) =\u003e number;\n\nlet multiply: mathFunction = (num1, num2) =\u003e num1 * num2;\n```\n\n```ts\ninterface mathFunction2 {\n  (a: number, b: number): number;\n}\n```\n\n* Define function signatures using `type` or `interface` to enforce structure across function variables.\n\n---\n\n### ❓ 6. Optional \u0026 Default Parameters\n\n```ts\nconst addAll = (a: number, b: number, c?: number): number =\u003e {\n  return c !== undefined ? a + b + c : a + b;\n};\n\nconst sumAll = (a: number, b: number, c: number = 2): number =\u003e {\n  return a + b + c;\n};\n```\n\n* `c?: number` = **optional parameter** (can be omitted).\n* `c: number = 2` = **default value** (used if not passed).\n\n```ts\nconst sumAll2 = (a: number = 10, b: number, c: number = 2) =\u003e a + b + c;\n```\n\n* Default values can also be assigned to parameters other than the last, but usage must match carefully.\n\n---\n\n### 📚 7. Rest Parameters\n\n```ts\nconst total = (...nums: number[]): number =\u003e {\n  return nums.reduce((prev, curr) =\u003e prev + curr);\n};\n```\n\n* `...nums: number[]` = accepts any number of arguments into a single array.\n* Perfect for aggregation and iteration.\n\n---\n\n### 🚫 8. The `never` Type\n\n#### Throwing Errors\n\n```ts\nconst createError = (errMsg: string): never =\u003e {\n  throw new Error(errMsg);\n};\n```\n\n* `never` means the function **never returns** (due to error or infinite loop).\n\n#### Infinite Loops (commented)\n\n```ts\n/* const infinite = () =\u003e {\n  let i: number = 1;\n  while (true) {\n    i++;\n  }\n}; */\n```\n\n* This also returns `never` because it never terminates.\n\n#### With Break (returns `void`)\n\n```ts\nconst infinite = () =\u003e {\n  let i: number = 1;\n  while (true) {\n    i++;\n    if (i \u003e= 100) break;\n  }\n};\n```\n\n---\n\n### ✅ 9. Type Guards\n\n#### Manual Type Checking\n\n```ts\nconst numberOrStringFunc = (value: number | string): string =\u003e {\n  if (typeof value === 'number') return 'number';\n  if (typeof value === 'string') return 'string';\n  return createError('This should never happen');\n};\n```\n\n* Type guards allow safe narrowing of union types.\n\n#### Reusable Guard Function\n\n```ts\nconst isNumber = (value: any): boolean =\u003e {\n  return typeof value === 'number';\n};\n\nconst numberOrStringFunc2 = (value: number | string): string =\u003e {\n  if (isNumber(value)) return 'number';\n  if (typeof value === 'string') return 'string';\n  return createError('This should never happen');\n};\n```\n\n* Improves readability and reusability by abstracting the guard logic.\n\n\n---\n\n## [Type Assertions, Unknown, and DOM Handling](#type-assertions-unknown-and-dom-handling)\n\n### 🧾 1. Type Assertions (a.k.a. Type Casting)\n\n```ts\ntype One = string;\ntype Two = string | number;\ntype Three = 'hello';\n```\n\n#### More to Less Specific (Widening)\n\n```ts\nlet aa: One = 'ntm';\nlet bb = aa as Two;    // ✅ Allowed: string → string | number\n```\n\n#### Less to More Specific (Narrowing)\n\n```ts\nlet cc = aa as Three;  // ✅ Allowed: string → 'hello' (but risky unless value matches exactly)\n```\n\n* TypeScript allows casting to more or less specific types using `as`.\n* **⚠️ Warning**: This bypasses safety checks — you tell TypeScript \"Trust me\".\n\n---\n\n### 🧩 2. JSX vs TypeScript Syntax for Assertions\n\n#### Non-JSX (e.g. Angular, TS files):\n\n```ts\nlet dd = \u003cOne\u003e'sas';\nlet ee = \u003cOne | Two\u003e'ntm';\n```\n\n* ✅ Valid in `.ts` files (non-JSX).\n* ❌ Not allowed in `.tsx` (React uses angle brackets for JSX elements).\n\n\u003e In `.tsx`, always use `as` syntax instead.\n\n---\n\n### ➕ 3. Return Value Assertion Example\n\n```ts\nconst addOrConcat = (a: number, b: number, c: 'add' | 'concat'): number | string =\u003e {\n  if (c === 'add') return a + b;\n  return '' + a + b;\n};\n```\n\n```ts\n// ❌ Error: TS can't guarantee return is a string\n// let myVal: string = addOrConcat(2, 2, \"concat\");\n\nlet myVal: string = addOrConcat(2, 2, \"concat\") as string; // ✅\n\nlet myVal2: number = addOrConcat(2, 2, \"concat\") as number; // ⚠️ Compiles, but incorrect!\n```\n\n* Type assertions **do not validate correctness** — use carefully!\n* In `myVal2`, a `string` is forcibly treated as a `number`, which may cause runtime bugs.\n\n---\n\n### 🕵️ 4. The `unknown` Type\n\n```ts\n// 10 as string; ❌ Error\n(10 as unknown) as string; // ✅ Allowed\n```\n\n* You can **double assert**: from any type to `unknown`, then to the desired type.\n* Avoid unless absolutely necessary (used when dealing with third-party or very dynamic data).\n\n---\n\n### 🌐 5. Working with the DOM\n\n#### Non-null Assertion (`!`)\n\n```ts\nconst myImg = document.querySelector('img')!; // Tells TS this will never be null\nmyImg.src;\n```\n\n* The `!` operator is the **non-null assertion** operator.\n* Use with caution — TypeScript will **not warn** if `querySelector` returns `null`.\n\n---\n\n#### Type Casting DOM Elements\n\n```ts\nconst img = document.getElementById('img') as HTMLImageElement;\nimg.src;\n```\n\n* You must **cast** DOM elements when accessing their specific properties (e.g., `.src` is not available on generic `HTMLElement`).\n* This ensures TypeScript knows the correct element type.\n\n---\n\n### ⚠️ Summary Tips\n\n| Scenario                     | TypeScript Behavior                     |\n| ---------------------------- | --------------------------------------- |\n| `as` type assertions         | Bypass type checking — be careful       |\n| `unknown`                    | Safer than `any`, forces type narrowing |\n| DOM queries                  | Often return `HTMLElement` or `null`    |\n| Use `as HTMLImageElement`    | To access image-specific properties     |\n| Avoid `as number` on strings | Could lead to silent logic errors       |\n\n---\n\nThis is an excellent and thorough overview of **advanced TypeScript concepts**, especially object-oriented programming and structural typing. Here's a structured summary of everything you've written for quick reference and learning:\n\n---\n\n## [OOP, Interfaces, Index Signatures, and Records](#oop-interfaces-index-signatures-and-records)\n\n\n### 1️⃣ **Classes with Access Modifiers**\n\n```ts\nclass CodeVis {\n  constructor(\n    public readonly name: string,\n    public music: string,\n    private age: number,\n    protected lang: string = 'BN'\n  ) {}\n  \n  public getAge() {\n    return `Hello! I am ${this.age}`;\n  }\n}\n```\n\n| Modifier    | Visibility                             |\n| ----------- | -------------------------------------- |\n| `public`    | Accessible everywhere                  |\n| `private`   | Only inside the class                  |\n| `protected` | Class + subclasses                     |\n| `readonly`  | Cannot be changed after initialization |\n\n---\n\n### 2️⃣ **Inheritance**\n\n```ts\nclass WebDev extends CodeVis {\n  constructor(public computer: string, name: string, music: string, age: number) {\n    super(name, music, age);\n  }\n\n  public getLang() {\n    return `I write in ${this.lang}`;\n  }\n}\n```\n\n---\n\n### 3️⃣ **Interfaces \u0026 Implementation**\n\n```ts\ninterface Musician {\n  name: string;\n  instrument: string;\n  play(action: string): string;\n}\n\nclass TestClass implements Musician {\n  constructor(public name: string, public instrument: string) {}\n\n  play(action: string): string {\n    return `${this.name} ${action} ${this.instrument}`;\n  }\n}\n```\n\n---\n\n### 4️⃣ **Static Properties**\n\n```ts\nclass Peeps {\n  static count = 0;\n  public id: number;\n\n  constructor(public name: string) {\n    this.id = ++Peeps.count;\n  }\n\n  static getCount() {\n    return Peeps.count;\n  }\n}\n```\n\n* Use `ClassName.staticProperty` to access static members.\n\n---\n\n### 5️⃣ **Getter \u0026 Setter with Validation**\n\n```ts\nclass Bands {\n  private dataState: string[] = [];\n\n  public get data(): string[] {\n    return this.dataState;\n  }\n\n  public set data(value: string[]) {\n    if (Array.isArray(value) \u0026\u0026 value.every(el =\u003e typeof el === 'string')) {\n      this.dataState = value;\n    } else {\n      throw new Error('Param is not an array of string');\n    }\n  }\n}\n```\n\n---\n\n### 6️⃣ **Index Signatures**\n\n#### a. Dynamic Keys\n\n```ts\ninterface Shop {\n  [index: string]: number;\n}\n\nconst shopTranscation: Shop = {\n  Pen: -100,\n  Chicken: -50,\n};\n\nlet prop2 = 'Pen';\nconsole.log(shopTranscation[prop2]); // ✔️\nconsole.log(shopTranscation['Dhaka']); // ❌ undefined but no error\n```\n\n#### b. With Specific Keys\n\n```ts\ninterface shopTranscation2 {\n  readonly [index: string]: number;\n  Pen: number;\n  Chicken: number;\n}\n\nconst Shop2: shopTranscation2 = {\n  Pen: 83,\n  Chicken: 115,\n  Test: 1907, // allowed due to index signature\n};\n```\n\n---\n\n### 7️⃣ **Iterating Over Object Keys**\n\n#### Using `keyof` or `typeof`\n\n```ts\ninterface StudentRes {\n  name: string;\n  roll: number;\n  classes?: number[];\n}\n\nconst stud1: StudentRes = {\n  name: 'Sami',\n  roll: 115,\n  classes: [7026, 1190],\n};\n\nfor (const key in stud1) {\n  console.log(`${key}: ${stud1[key as keyof typeof stud1]}`);\n}\n```\n\n---\n\n### 8️⃣ **Using Index Signature in Object**\n\n```ts\ninterface StudentRes2 {\n  [key: string]: string | number | number[] | undefined;\n  name: string;\n  roll: number;\n  classes?: number[];\n}\n```\n\n* Accessing `stud2.gpa` is allowed, even if not declared.\n* All keys must have types within the declared union.\n\n---\n\n### 9️⃣ **Using `Record` Utility Type**\n\n```ts\ntype Streams2 = 'salary' | 'bonus' | 'sideHustle';\ntype Income2 = Record\u003cStreams2, number | string\u003e;\n\nconst monthlyIncome: Income2 = {\n  salary: 100,\n  bonus: 115,\n  sideHustle: 1190, // string expected? allowed due to union\n};\n```\n\n#### Strict Alternative:\n\n```ts\ntype Income = Record\u003c'salary' | 'bonus' | 'sideHustle', number\u003e;\n```\n\n---\n\n### 🔚 Summary\n\n| Concept             | Key Feature                               |\n| ------------------- | ----------------------------------------- |\n| Class modifiers     | Encapsulation with `private`, `protected` |\n| Interface           | Contract enforcement                      |\n| Static fields       | Shared across instances                   |\n| Getters/Setters     | Controlled access to properties           |\n| Index Signature     | Allow unknown keys with known value types |\n| `Record` utility    | Type-safe object with predefined keys     |\n| `keyof` + Assertion | Safe dynamic property access              |\n\n---\n\n## [Generics](#generics)\n\n### 1. Basic Function with and without Generics\n\n```ts\nconst stringEcho = (arg: string): string =\u003e arg;\n```\n\nThis function returns the same string that is passed to it. But it's limited to `string` type.\n\n#### Using Generics\n\n```ts\nconst Echo = \u003cT\u003e(arg: T): T =\u003e arg;\n```\n\nThis version is more flexible. It accepts any type and returns the same type. The type `T` is inferred based on the argument.\n\n---\n\n### 2. Type Guard for Object Type\n\n```ts\nconst isObj = \u003cT\u003e(arg: T): boolean =\u003e {\n    return (typeof arg === 'object' \u0026\u0026 !Array.isArray(arg) \u0026\u0026 arg !== null);\n}\n```\n\n* Checks if a value is a non-null, non-array object.\n* Useful for filtering out arrays and null which are also of type `object` in JavaScript.\n\n#### Example Usage\n\n```ts\nconsole.log(isObj(true)); // false\nconsole.log(isObj(null)); // false\nconsole.log(isObj([1, 2, 3])); // false\nconsole.log(isObj('ntm')); // false\nconsole.log(isObj({ name: 'ntm' })); // true\n```\n\n---\n\n### 3. Truthy Check with Custom Logic\n\n```ts\nconst isTrue = \u003cT\u003e(arg: T): { arg: T, is: boolean } =\u003e {\n    if (Array.isArray(arg) \u0026\u0026 !arg.length) return { arg, is: false };\n    if (isObj(arg) \u0026\u0026 !Object.keys(arg).length) return { arg, is: false };\n    return { arg, is: !!arg };\n}\n```\n\nThis function checks whether a value is logically \"truthy\", with special rules:\n\n* Empty array: false\n* Empty object: false\n* Otherwise: Boolean(arg)\n\n#### Interface Version\n\n```ts\ninterface BoolCheck\u003cT\u003e {\n    arg: T,\n    is: boolean\n}\n\nconst isTrue2 = \u003cT\u003e(arg: T): BoolCheck\u003cT\u003e =\u003e {\n    // same logic as isTrue\n}\n```\n\n#### Example Usage\n\n```ts\nconsole.log(isTrue(false));     // { arg: false, is: false }\nconsole.log(isTrue({}));        // { arg: {}, is: false }\nconsole.log(isTrue([1,2,3]));   // { arg: [1,2,3], is: true }\n```\n\n---\n\n### 4. Constrained Generics with Interface\n\n```ts\ninterface HasID {\n    id: number;\n}\n\nconst processUser = \u003cT extends HasID\u003e(user: T): T =\u003e user;\n```\n\nThis function enforces that the passed object must have an `id` property of type `number`.\n\n```ts\nconsole.log(processUser({ id: 83, name: 'ntm' })); // ✅\n// console.log(processUser({ name: 'sas' })); ❌ Error\n```\n\n---\n\n### 5. Dynamic Property Access from Array of Objects\n\n```ts\nconst getUsersProperty = \u003cT extends HasID, K extends keyof T\u003e(users: T[], key: K): T[K][] =\u003e {\n    return users.map(user =\u003e user[key]);\n}\n```\n\n* `T` is a generic object type that must include an `id`.\n* `K` is a key of `T`, ensuring type safety for property access.\n\n#### Example:\n\n```ts\nconst userArray = [\n  { id: 1, name: 'Leanne', username: 'Bret', email: 'a@example.com' },\n  { id: 2, name: 'Ervin', username: 'Antonette', email: 'b@example.com' }\n];\n\nconsole.log(getUsersProperty(userArray, 'email')); // ['a@example.com', 'b@example.com']\n```\n\n---\n\n### 6. Generic Class with Getter/Setter\n\n```ts\nclass stateObj\u003cT\u003e {\n    private data: T;\n\n    constructor(value: T) {\n        this.data = value;\n    }\n\n    get state(): T {\n        return this.data;\n    }\n\n    set state(value: T) {\n        this.data = value;\n    }\n}\n```\n\n* A generic class that stores any type.\n* Maintains type throughout access and updates.\n\n#### Example:\n\n```ts\nconst store = new stateObj(\"ntm\");\nstore.state = \"cse\"; // ✅\n// store.state = 83;  // ❌ Type error\n```\n\n#### Solution for Multi-type\n\n```ts\nconst myState = new stateObj\u003c(string | number | boolean)[]\u003e([83]);\nmyState.state = [\"ntm\", 83, true]; // ✅\n```\n\n---\n\n### Summary of Concepts Covered\n\n* ✅ Generic Functions\n* ✅ Type Guards (`isObj`)\n* ✅ Logical Evaluation with Extra Rules (`isTrue`)\n* ✅ Interface-based Constraints\n* ✅ `keyof` and Indexed Access Types\n* ✅ Generic Classes with Encapsulation\n\n---\n\n## [Utility Types](#utility-types)\n\n### 1. `Partial\u003cType\u003e`\n\nMakes all properties in `Type` optional.\n\n```ts\ninterface Assignment {\n  studentId: string;\n  title: string;\n  grade: number;\n  verified?: boolean;\n}\n\nconst updateAssignment = (\n  assign: Assignment,\n  propsToUpdate: Partial\u003cAssignment\u003e\n): Assignment =\u003e {\n  return { ...assign, ...propsToUpdate };\n};\n\nconst assign1: Assignment = {\n  studentId: \"ntm\",\n  title: \"Computer Graphics\",\n  grade: 90,\n};\n\nconsole.log(updateAssignment(assign1, { grade: 100 }));\nconst assignGraded: Assignment = updateAssignment(assign1, { grade: 100 });\n```\n\n---\n\n### 2. `Required\u003cType\u003e` and `Readonly\u003cType\u003e`\n\n* `Required\u003cType\u003e`: Makes all properties required.\n* `Readonly\u003cType\u003e`: Makes all properties immutable.\n\n```ts\nconst recordAssignment = (assign: Required\u003cAssignment\u003e): Assignment =\u003e {\n  return assign;\n};\n\nconst assignVerified: Readonly\u003cAssignment\u003e = { ...assignGraded, verified: true };\n// assignVerified.grade = 90; // ❌ Error: Readonly\n\nrecordAssignment({ ...assign1, verified: true });\n```\n\n---\n\n### 3. `Record\u003cKeys, Type\u003e`\n\nConstructs an object type with keys of type `Keys` and values of type `Type`.\n\n```ts\nconst hexColorMap: Record\u003cstring, string\u003e = {\n  red: \"FF0000\",\n  green: \"00FF00\",\n  blue: \"0000FF\",\n};\n\ntype studentName = \"azraf\" | \"sami\";\ntype LetterGrades = \"A\" | \"B\" | \"C\" | \"D\" | \"U\";\n\nconst finalGrades: Record\u003cstudentName, LetterGrades\u003e = {\n  azraf: \"A\",\n  sami: \"B\",\n};\n\ninterface Grades {\n  assign1: number;\n  assign2: number;\n}\n\nconst gradeData: Record\u003cstudentName, Grades\u003e = {\n  azraf: { assign1: 90, assign2: 93 },\n  sami: { assign1: 85, assign2: 98 },\n};\n```\n\n---\n\n### 4. `Pick\u003cType, Keys\u003e` and `Omit\u003cType, Keys\u003e`\n\n* `Pick` creates a type by picking specific keys.\n* `Omit` creates a type by omitting specific keys.\n\n```ts\ntype AssignmentResult = Pick\u003cAssignment, \"studentId\" | \"grade\"\u003e;\nconst score: AssignmentResult = {\n  studentId: \"ntm\",\n  grade: 100,\n};\n\ntype AssignmentPreview = Omit\u003cAssignment, \"grade\" | \"verified\"\u003e;\nconst preview: AssignmentPreview = {\n  studentId: \"ntm\",\n  title: \"Test Project\",\n};\n```\n\n---\n\n### 5. `Exclude\u003cType, ExcludedUnion\u003e` and `Extract\u003cType, Union\u003e`\n\n* `Exclude`: Excludes types from a union.\n* `Extract`: Extracts matching types from a union.\n\n```ts\ntype adjustGrades = Exclude\u003cLetterGrades, \"U\"\u003e; // \"A\" | \"B\" | \"C\" | \"D\"\ntype highGrades = Extract\u003cLetterGrades, \"A\" | \"B\"\u003e; // \"A\" | \"B\"\n```\n\n---\n\n### 6. `NonNullable\u003cType\u003e`\n\nRemoves `null` and `undefined` from a type.\n\n```ts\ntype AllPossibleGrades = \"ntm\" | \"sas\" | null | undefined;\ntype NamesOnly = NonNullable\u003cAllPossibleGrades\u003e; // \"ntm\" | \"sas\"\n```\n\n---\n\n### 7. `ReturnType\u003cType\u003e`\n\nExtracts the return type of a function.\n\n```ts\ntype newAssign = { title: string; point: number };\nconst createNewAssign = (title: string, point: number): newAssign =\u003e {\n  return { title, point };\n};\n\ntype newAssign2 = ReturnType\u003ctypeof createNewAssign\u003e;\nconst tAssign: newAssign2 = createNewAssign(\"Utility Types\", 100);\nconsole.log(tAssign);\n```\n\n---\n\n### 8. `Parameters\u003cType\u003e`\n\nExtracts the parameter types of a function as a tuple.\n\n```ts\ntype AssignParams = Parameters\u003ctypeof createNewAssign\u003e;\nconst assignArgs: AssignParams = [\"Image Processing Project\", 100];\nconst tAssign2: newAssign = createNewAssign(...assignArgs);\nconsole.log(tAssign2);\n```\n\n---\n\n### 9. `Awaited\u003cType\u003e`\n\nHelps retrieve the resolved type inside a `Promise`.\n\n```ts\ninterface User {\n  id: number;\n  name: string;\n  username: string;\n  email: string;\n}\n\nconst fetchUsers = async (): Promise\u003cUser[]\u003e =\u003e {\n  const data = await fetch('https://jsonplaceholder.typicode.com/users')\n    .then((res) =\u003e res.json())\n    .catch((err) =\u003e {\n      if (err instanceof Error) {\n        console.log(err.message);\n      }\n    });\n\n  return data;\n};\n\n// Awaited extracts User[] from Promise\u003cUser[]\u003e\ntype FetchUsersReturnType = Awaited\u003cReturnType\u003ctypeof fetchUsers\u003e\u003e;\nfetchUsers().then((users) =\u003e console.log(users));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsk-azraf-sami%2Flearn-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsk-azraf-sami%2Flearn-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsk-azraf-sami%2Flearn-typescript/lists"}