{"id":18933840,"url":"https://github.com/mchamoudadev/typescript-guide","last_synced_at":"2025-10-15T11:42:46.327Z","repository":{"id":199551632,"uuid":"703173507","full_name":"mchamoudadev/typescript-guide","owner":"mchamoudadev","description":null,"archived":false,"fork":false,"pushed_at":"2023-10-11T17:48:20.000Z","size":16,"stargazers_count":2,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-08T11:57:29.379Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/mchamoudadev.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}},"created_at":"2023-10-10T18:24:31.000Z","updated_at":"2024-04-13T18:09:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"5cff3930-3ba6-4326-8726-2437a2f98c8e","html_url":"https://github.com/mchamoudadev/typescript-guide","commit_stats":null,"previous_names":["mchamoudadev/typescript-guide"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchamoudadev%2Ftypescript-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchamoudadev%2Ftypescript-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchamoudadev%2Ftypescript-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchamoudadev%2Ftypescript-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mchamoudadev","download_url":"https://codeload.github.com/mchamoudadev/typescript-guide/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232028770,"owners_count":18462506,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-08T11:56:37.628Z","updated_at":"2025-10-15T11:42:41.274Z","avatar_url":"https://github.com/mchamoudadev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"### What is TypeScript?\n\n**TypeScript** is a statically typed superset of JavaScript developed and maintained by Microsoft. It adds static types to JavaScript, which can make it easier to read and less prone to runtime errors. \n\n#### Why TypeScript?\n\n1. **Early Error Detection:** Catch errors early in development, reducing runtime errors.\n2. **Readability:** Type annotations make it easier to understand what values are expected.\n3. **Robustness:** The type system ensures more reliable, robust code.\n4. **Enhanced Tooling:** Improved autocompletion, type checking, and source documentation.\n5. **Scalability:** Facilitates the development of scalable, maintainable codebases.\n   \n\n### Installing TypeScript\n\n#### 1. Install Node.js and npm\nEnsure that [Node.js](https://nodejs.org/) and npm (Node Package Manager, which comes with Node.js) are installed on your system. You can check their installation by running:\n```shell\nnode -v\nnpm -v\n```\n\n#### 2. Install TypeScript Globally\nInstall TypeScript globally on your system using npm:\n```shell\nnpm install -g typescript\n```\nThis command installs the TypeScript Compiler (tsc) globally, so it can be accessed from any directory in your command line.\n\n### Compiling TypeScript Code\n\n#### 3. Compile TypeScript to JavaScript\nTypeScript (`.ts` files) needs to be compiled to JavaScript (`.js` files) to be run in a JavaScript runtime like Node.js or a web browser. Use the TypeScript Compiler (`tsc`) to compile TypeScript files:\n```shell\ntsc filename.ts\n```\nThis command compiles `filename.ts` to a JavaScript file named `filename.js`.\n\n### Running TypeScript Code\n\n#### 4. Run Compiled JavaScript\nUse Node.js to run the compiled JavaScript file:\n```shell\nnode filename.js\n```\n\n### Creating a TypeScript Project\n\n#### 5. Initialize a TypeScript Project\nNavigate to your project directory and run:\n```shell\ntsc --init\n```\nThis command creates a `tsconfig.json` file in your project directory, which configures the TypeScript Compiler options.\n\n#### 6. Configure TypeScript Compiler Options\nOpen `tsconfig.json` and configure the compiler options as per your project needs. Some commonly used options are:\n- `\"target\": \"es6\"`: Specifies the ECMAScript target version.\n- `\"module\": \"commonjs\"`: Specifies the module system.\n- `\"rootDir\": \"./src\"`: Specifies the root directory of your source files.\n- `\"outDir\": \"./dist\"`: Redirects the output structure to the directory.\n\n#### 7. Compile and Run TypeScript Code in One Step\nFor a smoother developer experience, you might want to compile and run TypeScript code in one step. To achieve this, you can use the `ts-node` package:\n```shell\nnpm install -g ts-node\n```\nThen, you can run TypeScript files directly:\n```shell\nts-node filename.ts\n```\n\n### Summary\n\n- **Install TypeScript**: Using npm, install TypeScript globally.\n- **Compile TypeScript**: Use `tsc` to compile `.ts` files to `.js`.\n- **Run JavaScript**: Use `node` to run the compiled `.js` files.\n- **TypeScript Project**: Use `tsc --init` to start a new TypeScript project and configure `tsconfig.json`.\n- **Run TypeScript Directly**: Use `ts-node` to run TypeScript code without manually compiling it.\n\n\n### Topic 1: Basic Types and Type Annotations\n\n#### Basic Types in TypeScript\nTypeScript includes several basic types which allow developers to specify and validate the data types they expect:\n\n- **`number`**: For numerical values.\n- **`string`**: For textual data.\n- **`boolean`**: For true/false values.\n- **`array`**: For arrays of other types.\n- **`tuple`**: For fixed-length arrays with specified types.\n- **`enum`**: For enumerated values.\n- **`any`**: For unknown or dynamic types.\n- **`void`**: For functions that don't return a value.\n- **`null`** and **`undefined`**: For values that are null or undefined.\n\n\n\n### Topic 2: Deep Dive into Basic Types\n\n#### 1. `number`\n\n- Used for integers and floating-point numbers.\n  \n  **Example:**\n  ```typescript\n  let age: number = 30;\n  let weight: number = 150.5;\n  ```\n\n#### 2. `string`\n\n- Used for textual data.\n  \n  **Example:**\n  ```typescript\n  let name: string = \"Alice\";\n  let greeting: string = `Hello, my name is ${name}`;\n  ```\n\n#### 3. `boolean`\n\n- Used for true/false values.\n  \n  **Example:**\n  ```typescript\n  let isAdult: boolean = true;\n  ```\n\n#### 4. `array`\n\n- Used for arrays of other types.\n  \n  **Example:**\n  ```typescript\n  let numbers: number[] = [1, 2, 3, 4, 5];\n  let names: string[] = [\"Alice\", \"Bob\", \"Charlie\"];\n  ```\n\n#### 5. `tuple`\n\n- Used for fixed-length arrays with elements of specified types.\n  \n  **Example:**\n  ```typescript\n  let person: [string, number] = [\"Alice\", 30]; // [name, age]\n  ```\n\n#### 6. `enum`\n\n- Used for creating named constants.\n  \n  **Example:**\n  ```typescript\n  enum Color {Red, Green, Blue}\n  let c: Color = Color.Green;\n  ```\n\n#### 7. `any`\n\n- Used when the type is unknown or dynamic.\n  \n  **Example:**\n  ```typescript\n  let variable: any = 4;\n  variable = \"string\";\n  variable = true;\n  ```\n\n#### 8. `void`\n\n- Commonly used as the return type of functions that do not return a value.\n  \n  **Example:**\n  ```typescript\n  function logMessage(message: string): void {\n      console.log(message);\n  }\n  ```\n\n#### 9. `null` and `undefined`\n\n- Special types that have only one value each (`null` and `undefined`).\n  \n  **Example:**\n  ```typescript\n  let u: undefined = undefined;\n  let n: null = null;\n  ```\n\n### Topic 3: Functions and Type Annotations\n\nFunctions play a critical role in TypeScript, and understanding how to work with types in function parameters and return values is crucial.\n\n#### Typing Function Parameters and Return Values\n\n- **Example:**\n  ```typescript\n  function greet(name: string): string {\n      return `Hello, ${name}`;\n  }\n  ```\n\n  **Explanation:**\n  - `name: string` - The `name` parameter must be a string.\n  - `: string` after the parameter list indicates that the function returns a string.\n\n\n#### 2. **Function Expressions**\nFunction expressions involve defining a function and assigning it to a variable. This function can be anonymous or named.\n\n```javascript\nconst add = function(a, b) {\n    return a + b;\n};\n```\n\nIn TypeScript, we can add type annotations to function expressions to specify the types of parameters and the return type of the function.\n\n### Typing Function Expressions in TypeScript\n\nWhen working with function expressions in TypeScript, you can specify the types of parameters and the return type to ensure type safety.\n\n**Example:**\n```typescript\nconst add: (a: number, b: number) =\u003e number = function(a, b) {\n    return a + b;\n};\n```\n\n#### Detailed Explanation:\n\n- **`(a: number, b: number) =\u003e number`**: This part is a type annotation for the function expression and it provides the following details:\n    - **`a: number, b: number`**: The parameters `a` and `b` should be of type `number`.\n    - **`=\u003e number`**: The function will return a value of type `number`.\n\n- **`function(a, b)`**: This is the function expression. Notice we didn't have to specify types for `a` and `b` here. TypeScript infers the types from the type annotation we provided.\n\n#### Why is this Useful?\n\n1. **Type Safety:** Ensures that the function parameters and return type are as intended, preventing unintended data types from being passed or returned.\n   \n2. **Code Intellisense:** Provides better development experience with intelligent code suggestions and parameter hints.\n   \n3. **Readability:** The type annotations serve as a form of documentation, making the code more readable and understandable to others (and to \"future you\").\n\n#### Use Cases:\n\n- **API Calls:** When you have a function that makes API calls, defining the expected input and output types can ensure that the data handling throughout the app is consistent and predictable.\n  \n- **Utility Functions:** For functions that perform calculations or data transformations, specifying types can prevent inadvertent errors due to unexpected data types.\n\n\n#### Optional and Default Parameters\n\n- **Example:**\n  ```typescript\n  function createGreeting(name: string, age?: number): string {\n      return age \n          ? `Hello, my name is ${name} and I am ${age} years old`\n          : `Hello, my name is ${name}`;\n  }\n  ```\n\n  **Explanation:**\n  - `age?: number` indicates that `age` is an optional parameter.\n  - The function can be called with either one or two arguments.\n\n\n\n### Arrow Functions in TypeScript\n\nArrow functions, introduced in ECMAScript 2015 (ES6), provide a concise syntax to define functions. They are especially useful for writing shorter function expressions. \n\n#### Basic Syntax of Arrow Functions\n\nThe basic syntax of an arrow function in JavaScript is:\n\n```javascript\nconst add = (a, b) =\u003e {\n    return a + b;\n};\n```\n\nIn TypeScript, you can add type annotations to the parameters of arrow functions, just like regular function expressions. Additionally, you can specify the return type of the function.\n\n### Typing Arrow Functions in TypeScript\n\n#### Example 1: Basic Type Annotations\n\n```typescript\nconst add: (a: number, b: number) =\u003e number = (a, b) =\u003e {\n    return a + b;\n};\n```\n\nIn this example:\n- **`(a: number, b: number) =\u003e number`**: This is a type annotation indicating the function takes two parameters of type `number` and returns a `number`.\n- **`(a, b) =\u003e {...}`**: This is the arrow function. The types of `a` and `b` are inferred from the type annotation.\n\n#### Example 2: Implicit Return\n\nIf the arrow function body consists of a single expression, you can omit the curly braces and the `return` keyword. This is known as an implicit return.\n\n```typescript\nconst add: (a: number, b: number) =\u003e number = (a, b) =\u003e a + b;\n```\n\n#### Example 3: Typing the Parameters Directly\n\nYou can also apply type annotations directly to the parameters in the function expression if the types are straightforward and the function is not too complex.\n\n```typescript\nconst add = (a: number, b: number): number =\u003e a + b;\n```\n\n#### Detailed Explanation:\n\n- **`a: number, b: number`**: The parameters `a` and `b` should be of type `number`.\n- **`: number`**: Indicates the function will return a number.\n- **`=\u003e a + b`**: The arrow `=\u003e` introduces the function body. Here, `a + b` is the expression whose result will be returned.\n\n\n###  Objects and Type Aliases\n\n#### Objects\nObjects in TypeScript can have specific types assigned to their properties.\n\n**Example:**\n```typescript\nconst user: { name: string; age: number } = { name: 'Alice', age: 30 };\n```\n\n#### Type Aliases\nType aliases create a new name for a type and can be used to provide a type to objects, making the code more DRY (Don’t Repeat Yourself).\n\n#### Example: Using Type Aliases with Objects\n```typescript\ntype User = { name: string; age: number };\nconst user: User = { name: 'Alice', age: 30 };\n```\n**Explanation:**\n- A `User` type is defined using `type User = { name: string; age: number }` to avoid repeating the object structure and to enhance readability.\n- The `user` object is typed with `User`, ensuring it adheres to the defined structure.\n\n### 2. Union Types\n\n#### Example: Accepting Multiple Types\n```typescript\ntype StringOrNumber = string | number;\nconst id: StringOrNumber = 'abc123';\n```\n**Explanation:**\n- The type `StringOrNumber` is defined as a union (`string | number`), indicating `id` can be either a string or a number.\n- This provides flexibility while still restricting `id` to the intended types.\n\n### 3. Intersection Types\n\n#### Example: Combining Types\n```typescript\ntype Named = { name: string };\ntype Aged = { age: number };\ntype Person = Named \u0026 Aged;\nconst person: Person = { name: 'Alice', age: 30 };\n```\n**Explanation:**\n- `Named \u0026 Aged` creates a new type `Person` that combines the properties of `Named` and `Aged`.\n- The `person` object must have all properties from both types, ensuring comprehensive typing.\n\n### 4. Nullable Types and Optional Chaining\n\n#### Example: Safe Property Access\n```typescript\nconst user = { profile: { name: 'Alice', age: 30 } };\nconst age = user?.profile?.age;\n```\n**Explanation:**\n- `user?.profile?.age` utilizes optional chaining (`?.`) to safely access nested properties, preventing runtime errors if `profile` is `null` or `undefined`.\n- This results in `age` being `30` if `profile` exists and `undefined` otherwise.\n\n### 5. Nullish Coalescing Operator\n\n#### Example: Default Value Assignment\n```typescript\nconst input = null;\nconst output = input ?? 'default';\n```\n**Explanation:**\n- `input ?? 'default'` uses the nullish coalescing operator (`??`) to assign a default value of `'default'` if `input` is `null` or `undefined`.\n- This ensures `output` is assigned a valid value even when `input` is nullish.\n\n### 6. Type Assertion\n\n#### Example: Asserting Variable Type\n```typescript\nlet unknownVar: unknown = \"I am a string\";\nlet strVar: string = (unknownVar as string).toUpperCase();\n```\n**Explanation:**\n- `(unknownVar as string)` tells TypeScript to treat `unknownVar` as a string, allowing the use of string methods like `toUpperCase`.\n- This is useful when the developer knows the type but TypeScript does not.# typescript-guide\n\n\n### 1. Interfaces\n\n#### Purpose of Interfaces\nInterfaces in TypeScript are used to define the contract (shape) of objects, acting as a blueprint that ensures an object adheres to a specific structure. This enables TypeScript to validate that objects have the required shape, enhancing type safety and code intelligibility.\n\n#### Problems Solved by Interfaces\n- **Inconsistent Object Structures:** Prevents bugs and errors resulting from objects not adhering to the expected shape.\n- **Reusability:** Allows developers to define a structure once and use it across multiple objects, making the code DRY (Don't Repeat Yourself).\n- **Enhanced Autocompletion:** Improves developer experience by providing precise autocompletion and inline documentation in IDEs.\n\n### Detailed Explanation and Examples\n\n#### Basic Interface Usage\n\n##### Example: Defining and Using an Interface\n```typescript\ninterface User {\n    name: string;\n    age: number;\n}\n\nconst alice: User = { name: 'Alice', age: 30 };\n```\n##### Explanation\n- **Defining:** The `User` interface is defined to prescribe an object shape that includes `name` (string) and `age` (number).\n- **Using:** The object `alice` is typed with `User`, ensuring it adheres to the required shape.\n\n#### Extending Interfaces\n\n##### Example: Extending an Interface to Create a New Interface\n```typescript\ninterface Admin extends User {\n    permissions: string[];\n}\n\nconst bob: Admin = { name: 'Bob', age: 35, permissions: ['read', 'write'] };\n```\n##### Explanation\n- **Extending:** The `Admin` interface extends `User`, inheriting its properties and adding a new `permissions` property.\n- **Using:** The object `bob` must satisfy the structure of `Admin`, which includes properties from `User` as well.\n\n\n### Optional Properties\n\nOptional properties in an interface indicate that the property may or may not exist on objects adhering to the interface. They are defined by appending a `?` to the property name.\n\n#### Example: Utilizing Optional Properties\n```typescript\ninterface Product {\n    id: number;\n    name: string;\n    description?: string;\n}\n\nconst phone: Product = {\n    id: 1,\n    name: 'Smartphone'\n};\n```\n##### Explanation\n- **Defining:** The `description` property is defined as optional (`description?`) in the `Product` interface, indicating it may be omitted.\n- **Using:** The `phone` object adheres to `Product` without providing a `description`, and TypeScript doesn’t raise an error due to the property being optional.\n\n#### Scenario: Form Handling\n- **Problem:** When handling form submissions, some fields might be optional and should be handled without causing TypeScript errors.\n- **Solution:** Define the form data interface with optional properties for fields that are not required.\n\n```typescript\ninterface FormData {\n    username: string;\n    email?: string;\n}\n\nconst handleSubmit = (data: FormData) =\u003e {\n    // Handle submission\n};\n```\n- The `email` field is not required for form submission, but if provided, must be a string.\n\n### Readonly Properties\n\nReadonly properties can only be assigned when an object is first created and cannot be changed afterward. They are defined by prefixing the property name with `readonly`.\n\n#### Example: Utilizing Readonly Properties\n```typescript\ninterface Configuration {\n    readonly apiUrl: string;\n    timeout: number;\n}\n\nconst config: Configuration = {\n    apiUrl: 'https://api.example.com',\n    timeout: 3000\n};\n\n// Error: Cannot assign to 'apiUrl' because it is a read-only property\nconfig.apiUrl = 'https://newapi.example.com';\n```\n##### Explanation\n- **Defining:** `apiUrl` is defined as readonly, meaning it can't be reassigned after object creation.\n- **Using:** Trying to change `apiUrl` after the `config` object is created results in a TypeScript error, preventing unintended modifications.\n\n#### Scenario: Configuration Object\n- **Problem:** Avoid accidental changes to configuration settings after they have been set initially.\n- **Solution:** Define the configuration interface with readonly properties to ensure they are not modified after being initially set.\n\n```typescript\ninterface AppConfiguration {\n    readonly serviceUrl: string;\n    readonly maxRetries: number;\n}\n\nconst appConfig: AppConfiguration = {\n    serviceUrl: 'https://myservice.example.com',\n    maxRetries: 5\n};\n\n// Application code...\n\n// Error: Can't modify readonly property\nappConfig.serviceUrl = 'https://newservice.example.com';\n```\n- The `serviceUrl` and `maxRetries` properties cannot be changed after `appConfig` is initialized, ensuring stability in configuration throughout the application.\n\n### Summary\n\n- **Optional Properties:** Provide flexibility by allowing objects to optionally include certain properties.\n- **Readonly Properties:** Ensure stability by preventing properties from being changed after object creation.\n\n\n### Scenarios and Solutions using Interfaces\n\n#### Scenario: API Data Validation\n\n- **Problem:** When fetching data from an API, ensuring the received data adheres to the expected shape.\n- **Solution:** Define an interface representing the expected data shape and type the API response with it.\n\n##### Example: Typing API Data with an Interface\n```typescript\ninterface ApiResponse {\n    data: { id: number; name: string };\n    status: string;\n}\n\nfetch('https://api.example.com/data')\n    .then(response =\u003e response.json())\n    .then((data: ApiResponse) =\u003e {\n        console.log(data.data.name);\n    });\n```\n##### Explanation\n- The `ApiResponse` interface ensures the fetched data adheres to the expected shape, preventing potential runtime errors when accessing properties.\n\n### Introduction to Generics in TypeScript\n\n#### What is a Generic?\n\nGenerics allow developers to create functions, classes, and interfaces that work with a variety of data types while preserving the benefits of type safety. Essentially, they provide a way to create reusable components that can operate on different types without sacrificing type information.\n\n#### Why Use Generics?\n\n1. **Type Safety**: Generics ensure that the data types of variables are not lost during operations.\n   \n2. **Code Reusability**: Write once, use with any type. This prevents code duplication for each data type.\n   \n3. **Maintainability**: A single, consistent logic to manage and update.\n\n## Example 1: The `contains` Function\n\n#### Without Generics:\n\n##### Code Representation:\n\n```typescript\nfunction contains(arr: any[], item: any): boolean {\n    return arr.includes(item);\n}\n```\n\n##### Compile and Runtime Problems:\n\n- **Compile-Time**: No issues, since the function accepts any type.\n- **Runtime**: Possibility of logical errors due to type mismatching (e.g., comparing numbers with strings).\n\n##### Test Example:\n\n```typescript\nconsole.log(contains([1, 2, 3], '2')); // false, but no type error\n```\n\n##### Code Duplication:\n\nTo maintain type safety, you might create additional functions:\n\n```typescript\nfunction containsNumber(arr: number[], item: number): boolean { /* ... */ }\nfunction containsString(arr: string[], item: string): boolean { /* ... */ }\n```\n\n#### With Generics:\n\n##### Code Representation:\n\n```typescript\nfunction contains\u003cT\u003e(arr: T[], item: T): boolean {\n    return arr.includes(item);\n}\n```\n\n##### Compile and Runtime Safety:\n\n- **Compile-Time**: Type errors will be caught.\n- **Runtime**: Reduced risk of logical errors due to consistent typing.\n\n##### Test Example:\n\n```typescript\nconsole.log(contains\u003cnumber\u003e([1, 2, 3], '2')); // Type error\n```\n\n### Example 2: The `Pair` Interface\n\n#### Without Generics:\n\n##### Code Representation:\n\n```typescript\ninterface NumberPair {\n    first: number;\n    second: number;\n}\n```\n\n##### Compile and Runtime Problems:\n\n- **Compile-Time**: You will get type errors if you try to assign mismatching types.\n- **Runtime**: Type safety is preserved but at the cost of flexibility and code duplication.\n\n##### Test Example:\n\n```typescript\nlet pair: NumberPair = {first: 1, second: '2'}; // Type error\n```\n\n##### Code Duplication:\n\nTo allow different types, you create additional interfaces:\n\n```typescript\ninterface StringPair {\n    first: string;\n    second: string;\n}\n```\n\n#### With Generics:\n\n##### Code Representation:\n\n```typescript\ninterface Pair\u003cT, U\u003e {\n    first: T;\n    second: U;\n}\n```\n\n##### Compile and Runtime Safety:\n\n- **Compile-Time**: Errors if assigned types do not match the declared generic types.\n- **Runtime**: Safety through consistent typing without sacrificing flexibility.\n\n##### Test Example:\n\n```typescript\nlet pair: Pair\u003cnumber, string\u003e = {first: 1, second: '2'}; // No error\nlet invalidPair: Pair\u003cnumber, string\u003e = {first: 1, second: 2}; // Type error\n```\n\n### Conclusion:\n\nThrough the testing examples, we observe that without generics, we either compromise type safety (leading to potential runtime errors) or end up with code duplication to maintain type safety across various data types. With generics, we preserve type safety and prevent code duplication, enhancing code reliability, and maintainability by catching errors during compile time and reducing logical errors at runtime.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchamoudadev%2Ftypescript-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmchamoudadev%2Ftypescript-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchamoudadev%2Ftypescript-guide/lists"}