<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Audrey Kadjar</title>
    <description>The latest articles on DEV Community by Audrey Kadjar (@audreyk).</description>
    <link>https://dev.to/audreyk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1190837%2F4883784d-9bb3-4c36-9f1c-03ab8d2f9f4b.jpg</url>
      <title>DEV Community: Audrey Kadjar</title>
      <link>https://dev.to/audreyk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/audreyk"/>
    <language>en</language>
    <item>
      <title>Google Cloud Run Hackathon: Building Lexi — a Multi-Agent AI Legal Assistant for Individuals</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Fri, 07 Nov 2025 07:42:40 +0000</pubDate>
      <link>https://dev.to/audreyk/google-cloud-run-hackathon-building-lexi-a-multi-agent-ai-legal-assistant-5d1p</link>
      <guid>https://dev.to/audreyk/google-cloud-run-hackathon-building-lexi-a-multi-agent-ai-legal-assistant-5d1p</guid>
      <description>&lt;p&gt;It all started when I was reviewing an employment contract for a new job offer and found that I was struggling to understand the legal jargon.&lt;/p&gt;

&lt;p&gt;I realized &lt;strong&gt;how difficult it can be for individuals to truly understand complex legal language&lt;/strong&gt;. Legal documents are often dense, time-consuming, and intimidating to review. Most people struggle to grasp key clauses and identify potential risks, particularly in employment or freelance agreements.&lt;/p&gt;

&lt;p&gt;That’s where Lexi comes in: a &lt;strong&gt;multi-agent AI legal assistant&lt;/strong&gt; designed to make contract analysis clear, accessible, and easy to understand for &lt;strong&gt;individuals&lt;/strong&gt;. Built for the &lt;strong&gt;&lt;a href="https://run.devpost.com/" rel="noopener noreferrer"&gt;Google Cloud Run Hackathon&lt;/a&gt;&lt;/strong&gt;, Lexi focuses on delivering &lt;strong&gt;accurate&lt;/strong&gt;, &lt;strong&gt;structured insights&lt;/strong&gt; without overwhelming the user.&lt;/p&gt;

&lt;p&gt;Lexi’s vision is to help people understand any legal document, anywhere in the world. For now, it’s trained specifically on employment contracts in English under German law, as part of this project’s scope.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ How It Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You upload your employment, freelance, or NDA contract.&lt;/li&gt;
&lt;li&gt;Lexi analyzes each clause using multiple AI agents.&lt;/li&gt;
&lt;li&gt;On the frontend, Lexi streams the analysis in real time for a smooth, interactive experience.&lt;/li&gt;
&lt;li&gt;It highlights potential risks, compares clauses to standard legal documents, and explains everything in plain, human-friendly language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, Lexi makes legal document understanding faster, clearer, and even enjoyable.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 System Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                           ┌───────────────────────────────┐
                           │        Frontend (React)       │
                           │-------------------------------│
                           │ • Upload contract (PDF/Text)  │
                           │ • View clause analysis (live) │
                           │                               │
                           └──────────────┬────────────────┘
                                          │
                             JSON POST /contracts/analyze
                                          │
                                          ▼
                            ┌───────────────────────────────┐
                            │         FastAPI Backend       │
                            │        (Runs on Cloud Run)    │
                            │-------------------------------│
                            │ 1️⃣ Receives contract payload  │
                            │ 2️⃣ Extracts text (if PDF)     │
                            │ 3️⃣ Sends to CoreOrchestrator  │
                            │ 4️⃣ Streams structured JSON     │
                            │     chunks back to frontend   │
                            └──────────────┬────────────────┘
                                           │
                                           ▼
                     ┌────────────────────────────────────────────┐
                     │       Google ADK Agent System (Vertex AI)  │
                     │--------------------------------------------│
                     │ 🧭 CoreOrchestrator (LLM)                  │
                     │     ├─ ClauseExtractorAgent (LLM)          │
                     │     ├─ StandardClauseRetriever (Embed)     │
                     │     ├─ ClauseComparisonAgent (LLM)         │
                     │     └─ RiskAnalysisAgent (LLM)             │
                     │                                            │
                     └────────────────────────────────────────────┘
                                           │
                                           ▼
                           Streamed JSON → FastAPI → React
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧩 Stack Overview
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React (Cloud Run)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: FastAPI (Cloud Run)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: Firestore (for embeddings)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLMs&lt;/strong&gt;: gemini-embedding-001, gemini-2.0-flash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCR&lt;/strong&gt;: In-memory PDF text extraction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerization&lt;/strong&gt;: Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: Google Cloud Run&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 Multi-Agent System
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RootOrchestratorAgent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Coordinates all specialized agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SequentialAgent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensures ordered clause processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ClauseExtractorAgent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extracts clauses from the contract&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;StandardClauseRetriever&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Retrieves reference clauses from Firestore embeddings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ComparisonAgent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Detects deviations from standard clauses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RiskAnalysisAgent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Explains potential issues in plain language&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All agents collaborate through an orchestrator and shared state — creating a flexible and extensible system for document intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 What I Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to &lt;strong&gt;orchestrate multi-agent systems&lt;/strong&gt; using &lt;strong&gt;Google ADK&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;How to integrate &lt;strong&gt;embeddings with Firestore&lt;/strong&gt; for semantic retrieval &lt;/li&gt;
&lt;li&gt;How to deploy &lt;strong&gt;AI workloads&lt;/strong&gt; on &lt;strong&gt;Google Cloud Run&lt;/strong&gt; efficiently&lt;/li&gt;
&lt;li&gt;How to design &lt;strong&gt;real-time streaming UIs&lt;/strong&gt; with FastAPI and React&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏆 Accomplishments
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Combining &lt;strong&gt;Gemini&lt;/strong&gt; models, &lt;strong&gt;Google ADK&lt;/strong&gt;, &lt;strong&gt;Firestore&lt;/strong&gt; to create an AI app that improves a process and solves a real-world problem.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;Cloud Run&lt;/strong&gt; to deploy services seamlessly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 What’s Next
&lt;/h2&gt;

&lt;p&gt;🔹 Expand to more document types (leases, NDAs, terms of service)&lt;br&gt;
🔹 Add conversational Q&amp;amp;A (“Ask Lexi about clause 5”)&lt;br&gt;
🔹 Support multiple languages for global accessibility&lt;br&gt;
🔹 Explore secure authentication and saved session histories&lt;/p&gt;

&lt;p&gt;You can explore the project’s code on the &lt;a href="https://github.com/AudreyKj/google-run-hackaton-2025-lexi" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;—feel free to share any feedback. Wishing the best of luck to everyone!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>googlecloud</category>
      <category>googlecloudrun</category>
      <category>agents</category>
    </item>
    <item>
      <title>📦 🐳 Explaining Docker to My Parents (With Visuals)</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Mon, 02 Jun 2025 16:13:16 +0000</pubDate>
      <link>https://dev.to/audreyk/explaining-docker-to-my-parents-with-visuals-nhm</link>
      <guid>https://dev.to/audreyk/explaining-docker-to-my-parents-with-visuals-nhm</guid>
      <description>&lt;p&gt;Over dinner during the last Christmas holiday, my cousin, who works in maritime logistics, explained his job managing shipping containers. The next day, during a car ride with my parents, I casually mentioned that software engineers also use the concept of "containers" to deliver applications.&lt;/p&gt;

&lt;p&gt;My parents asked me to explain. That innocent question sparked an hour-long explanation of Docker in the backseat 😅 &lt;/p&gt;

&lt;p&gt;It turned out to be a rewarding experience because it challenged how well I understood it. So, I thought I'd recreate that conversation here (with visuals!) to help others understand Docker.&lt;/p&gt;




&lt;h3&gt;
  
  
  What's Docker?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“Docker? What's that?”&lt;/em&gt; my parents asked, intrigued.&lt;/p&gt;

&lt;p&gt;Docker is a program you install on your computer. It lets you package your app and everything it needs (code, libraries, settings) into a unit of software called a container.&lt;/p&gt;

&lt;p&gt;Developers use Docker to package applications so they can run reliably and consistently.&lt;/p&gt;




&lt;h3&gt;
  
  
  But why do we need Docker?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“Okay, that sounds interesting,”&lt;/em&gt; my parents asked, “&lt;em&gt;but what problem does it actually solve?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The main benefits of using Docker are consistency and speed.&lt;/p&gt;

&lt;p&gt;In shipping logistics, containers are used to transport goods from one place to another. The point of using containers is consistency. No matter what’s inside (a couch, TVs, or shoes), it all fits into a standard-sized box that ships easily.&lt;/p&gt;

&lt;p&gt;In software engineering, we have a similar concept.&lt;/p&gt;

&lt;p&gt;When we deploy an application, we want to package everything it needs - its code, configuration, and dependencies (like libraries) - into a box that can run anywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦 Physical Container       🐳 Docker Container
────────────────────       ─────────────────────
🚢 Shipping Box            📦 Docker Container
🧾 Packing List            🧱 Docker Image
🖥️ TVs                     💻 App Code
👟 Shoes                   📚 Libraries
📘 Books                   ⚙️ Config Files
🍽️ Dishes                 🧪 Dependencies

🔒 Secure + Sealed         🔐 Isolated + Portable
🚚 Easy to Transport       📦 Easy to Deploy
🌍 Standard Size           📐 Consistent Environment

        ➡️ Goal: Standardize Delivery ⬅️
     🛳️ Goods               🧑‍💻 Software
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We work with multiple environments in software engineering: for example, the test environment or the production environment with which customers interact. Docker ensures that your application behaves the same, no matter in which environment it runs. &lt;/p&gt;

&lt;p&gt;Unlike older methods like Virtual Machines, Docker doesn’t need to simulate a full operating system, so it's fast.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wait... What’s a Virtual Machine?
&lt;/h3&gt;

&lt;p&gt;My mom looked back and said: &lt;em&gt;“Virtual machine? You lost us there, honey.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fair enough! 😁&lt;/p&gt;

&lt;p&gt;A virtual machine (VM) allows a physical computer to simulate multiple independent computers within itself. Each VM has its own operating system (OS), virtual CPU, memory, and storage. This setup provides complete separation but is resource-intensive.&lt;/p&gt;

&lt;p&gt;Unlike VMs, Docker containers share the host’s operating system instead of running a full OS. Yet, they stay isolated from each other and the host using Linux features like namespaces (for separating processes and networks) and cgroups (for managing resources). This makes containers fast, lightweight, and secure, which is ideal for quick and consistent software deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoof555mydqbr3qarp31.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoof555mydqbr3qarp31.jpg" alt="Image description" width="673" height="282"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(image credit: this diagram was taken from Docker's website)&lt;/em&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  How is Docker used for delivery?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;"Ok, but why do you use this? Why can't you just deploy your application directly?"&lt;/em&gt; Another solid question my dad raised with a frown.&lt;/p&gt;

&lt;p&gt;In software engineering, we deploy applications to servers to make them accessible to users. A server is just another (usually powerful) computer, often hosted by cloud providers like AWS or Google Cloud. Deploying to a server involves copying your app’s code onto the machine and running it so that others can access your app.&lt;/p&gt;

&lt;p&gt;You can deploy your app directly to a server—but that’s like shipping loose cargo. If the server’s environment is different from yours (like a different library version), your app might not work.&lt;/p&gt;

&lt;p&gt;Docker lets you ship your app with its environment. So as long as the server supports Docker, your app runs exactly as it did on your computer.&lt;/p&gt;


&lt;h3&gt;
  
  
  Demo: How do you use Docker?
&lt;/h3&gt;

&lt;p&gt;At this point, I wasn’t sure if my parents were impressed… or completely lost. Then my mom asked one last question: &lt;em&gt;“So how do you use Docker? It sounds complicated.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using Docker is actually pretty straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install Docker Desktop&lt;/strong&gt; on your computer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In your app’s folder, create a file called a &lt;strong&gt;Dockerfile&lt;/strong&gt;. In this file, you describe how to package your app — specifying the base system, required dependencies, and how to start the app. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a simple Dockerfile for a Node.js app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use an official Node.js runtime as the base image&lt;/span&gt;
FROM node:18

&lt;span class="c"&gt;# Create and set the working directory inside the container&lt;/span&gt;
WORKDIR /app

&lt;span class="c"&gt;# Copy package.json and package-lock.json&lt;/span&gt;
COPY package.json ./

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
RUN npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copy the rest of your application code&lt;/span&gt;
COPY &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Expose the port your app runs on&lt;/span&gt;
EXPOSE 3000

&lt;span class="c"&gt;# Command to run your app&lt;/span&gt;
CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;, &lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Build a Docker image:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a &lt;strong&gt;Docker image&lt;/strong&gt;. It’s not a picture but a set of files that contains everything needed to run your app (like a blueprint for creating the container). These files are stored inside Docker’s internal storage area. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the container:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command starts a container, which is a running instance of the image you built in the previous step. &lt;/p&gt;

&lt;p&gt;Your app is now running inside a container!&lt;/p&gt;




&lt;p&gt;Hope this guide was helpful! Let me know in the comments what you thought of it and if you have any questions 😊 &lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>explainlikeimfive</category>
      <category>programming</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Tue, 11 Mar 2025 18:24:49 +0000</pubDate>
      <link>https://dev.to/audreyk/-2lp9</link>
      <guid>https://dev.to/audreyk/-2lp9</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/audreyk" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1190837%2F4883784d-9bb3-4c36-9f1c-03ab8d2f9f4b.jpg" alt="audreyk"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/audreyk/typescript-utility-types-1fnn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🛠️🧩 TypeScript Utility Types - a cheat sheet&lt;/h2&gt;
      &lt;h3&gt;Audrey Kadjar ・ Mar 7&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>🛠️🧩 TypeScript Utility Types - a cheat sheet</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Fri, 07 Mar 2025 08:30:26 +0000</pubDate>
      <link>https://dev.to/audreyk/typescript-utility-types-1fnn</link>
      <guid>https://dev.to/audreyk/typescript-utility-types-1fnn</guid>
      <description>&lt;p&gt;Utility types look complicated, but they are actually simple and super handy. Let's say you have a type and you want to customize it for a use case. Instead of duplicating that type and modifying it to fit that use case, you can use a utility type.&lt;/p&gt;

&lt;p&gt;Here is a recap of some utility types. You can play with the examples on the &lt;a href="https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnIhwC2EAXMumFKAOYDc+yct5hArsQEbSMC+uQQHohABThQwwOABtBCAPYgqydpigBGCuMnSZAHgzQAfMgC8OQiTYAiAILsAJlAgBPG8j71kI5AAMWCD9kYHRkBQAHKSVZXEVlMFV1ACZtCSlZQ3VTC2xmVgoAZkLPb18-IlJg0PCo4Bi5eJU1aAAWNN1Moygcy0q2YtKfIWQAUSgoBSgKABVXCJQAchBOHihFkLCQBUS4dHRgWiIuGRQwBWQweaWqGhBaRbilZvUAVg6Mg27evIB3AAs4JAAG7QIolLzDMYTKYUADyXAAVhAEIkZMBIFBZMhiHBXOEQDJ8egFghgDB8QBrba-EDICKTBa6CDoAA0zBAjmQiwBQIgoPWyEcChZhB2yAgAA9QolQJdrtydJ8siZHk1Ei0oAA2D56FU9cw4SG+BBwOk8CXEKLE0BIEKJXGU0WyGT0xnQKSiyLRIhyXAiABKEAAjuxgC5HIJQJj4HaAMqAhY4JiKGRTAD8FFudEYBF+wEcYH+mY43F4uAETwSlETEC0yCDofDEEc+gTcAWP2QqdhyBstBcEBANnZ+cL-worQADENfFwdv83ZEPcBnS4cWbHECpq4qyp0LXUg2Q2GI23az8e9M+yd2BAbHxhuNJtfRO7JPieQWixsasRQgc9whHSVxJoseRXlm1A5p4GxcOwiQuE2EbAfKYGNqeLbnh2EDGI8-pCEGcDCoSu57hq6gUERJFEvqXb9BQ9jokgI75GwySvKUuCagAdIEhrJFq3gEdCL4UAAwma2y7PshwgRciyBHBKJwC09qbMwyAuMRAC0ShEkuTJXIIBFBooUCRrgoEoAGCinIaNjEf+w7IAAPn2moeO5-Z3lQNiMORSTQLZpzoFRKJTK2IUQOy2b3D8TBOaAjF2I4zkyli5xQCOTCaoxQa0OwMgSGg6g5QQhUsmAjEAOK+Yk3Q5V4JkiKIwAIJSyDyM8iQRO1TqON02j9fq7I2P0Ng-AxfYOM4bgPt11Z9R1LbdEebUdaNfYTVN1gpU4LjuOygTggIIgIsiqLIOimLYri+L6cSpLklSNJ0gyy7MmyHJcoprAbMKorSRK0oqHK1mKiN3RjTtixAA" rel="noopener noreferrer"&gt;TypeScript Playground&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partial
&lt;/h3&gt;

&lt;p&gt;This utility type makes all properties of a type optional. This is useful if you need to update or extend a type, but don't need to provide every property. However, TypeScript still enforces correct types for each property and does not allow arbitrary properties-all properties must be included in the type definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// age is optional&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// name is optional&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Error: Type 'number' is not assignable to type 'string'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;whatever&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Error: Object literal may only specify known properties&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// can be empty since it makes all properties optional&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Required
&lt;/h3&gt;

&lt;p&gt;The opposite of Partial, it makes all properties of a type mandatory. This can be useful when you want to make sure that a type has all of its properties set, even if it was previously optional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shape1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// both properties are mandatory&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shape2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Required&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;//Error: Property 'width' is missing in type '{ color: string; }' but required in type 'Required&amp;lt;Shape&amp;gt;'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Readonly
&lt;/h3&gt;

&lt;p&gt;This makes all properties of a type read-only, meaning they can't be reassigned after creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error: Cannot assign to 'age' because it is a read-only property&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Record
&lt;/h3&gt;

&lt;p&gt;This creates an object type with keys of type K and values of type T. It’s useful when you want to enforce a shape for an object with dynamic keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Administrator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Regular User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pick
&lt;/h3&gt;

&lt;p&gt;This type constructs a new type by picking a set of properties K from type T. It’s useful when you need a subset of properties from an existing type.&lt;/p&gt;

&lt;p&gt;In this example, &lt;code&gt;pickedUser&lt;/code&gt; object is correctly typed because it includes only the name property. It is then assigned to an object, which matches the expected type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickedUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickedUser2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Error: 'age' does not exist in type 'Pick&amp;lt;User, "name"&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What do utility types compile to?
&lt;/h3&gt;

&lt;p&gt;Because TypeScript is a superset of JavaScript, utility types exist only at compile time to enforce type safety and do not affect runtime output. The final JavaScript output is just plain JavaScript objects with no TypeScript type constraints.&lt;/p&gt;

&lt;p&gt;The examples above compile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//Partial&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; 

&lt;span class="c1"&gt;//Required&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shape1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Readonly&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Record&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Administrator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Regular User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest User&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Pick &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make your own utility types
&lt;/h3&gt;

&lt;p&gt;TypeScript enables the creation of custom utility types using generics and mapped types. For instance, you can define your own version of Partial.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;keyof T&lt;/code&gt; type in TypeScript represents all the property names (keys) of T. In the example, &lt;code&gt;[K in keyof T]&lt;/code&gt; iterates over each key, while &lt;code&gt;T[K]&lt;/code&gt; ensures the property retains its original type, and &lt;code&gt;?&lt;/code&gt; makes each property optional.&lt;/p&gt;

&lt;p&gt;The custom &lt;code&gt;MyPartial&amp;lt;T&amp;gt;&lt;/code&gt; type behaves similarly to &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;, making all properties optional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MyPartial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]?:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyPartial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// 'age' is optional&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope this was helpful! You can find all the available utility types in the &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html" rel="noopener noreferrer"&gt;TypeScript documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://bsky.app/profile/audreykadjar.bsky.social" rel="noopener noreferrer"&gt;BlueSky&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>I've launched a new web app to generate colors with AI</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Fri, 06 Dec 2024 08:57:22 +0000</pubDate>
      <link>https://dev.to/audreyk/ive-launched-a-web-app-to-generate-colors-with-ai-7dm</link>
      <guid>https://dev.to/audreyk/ive-launched-a-web-app-to-generate-colors-with-ai-7dm</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsr9kh8gg431wz611kvu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsr9kh8gg431wz611kvu.jpg" alt="Image description" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve just launched my year’s side project!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.colorspot.app" rel="noopener noreferrer"&gt;color spot&lt;/a&gt; - a web app where users can generate colors with AI, images and moods, as well as explore and save their favorites from the community collection.&lt;/p&gt;

&lt;p&gt;Check it out and let me know what you think :) I would appreciate any feedback (positive or negative) as I'd like to improve the app.&lt;/p&gt;

&lt;p&gt;If you like it, please follow the project on Instagram &lt;a href="https://www.instagram.com/colorspot.app/" rel="noopener noreferrer"&gt;@colorspot.app&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>🛠️📚 Classes with TypeScript - a cheat sheet</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Wed, 16 Oct 2024 17:24:05 +0000</pubDate>
      <link>https://dev.to/audreyk/classes-with-typescript-a-cheat-sheet-39ep</link>
      <guid>https://dev.to/audreyk/classes-with-typescript-a-cheat-sheet-39ep</guid>
      <description>&lt;p&gt;TypeScript enhances JavaScript classes by providing additional features that make it easier to enforce contracts and catch errors at compile time. It's important to note that these TypeScript-specific features are removed at compile time, resulting in standard JavaScript classes.&lt;/p&gt;

&lt;p&gt;Here is a cheat sheet summarizing these additional features. You can play with the examples below in this &lt;a href="https://www.typescriptlang.org/play/?#code/FDD0oRgAgWihBAxogpgZzVAtgewCYCWAZgSgE6YoAeAhlgA4A2KwijNGUAwjgK4B2AF3JQA3sCiSo9XgCNGBRFER8hALij9eWWeQDcEqfTI5hiYXmw0qPAYI1ad+w5OMEAbjWFQAFhwBCKCj8AEroKIK26praumQGUlBogl6KUAT8yTT8qFH2MU5kUAC8UAAMBi7KOJmCZLzmOGQAFFjWeQ6x5ACU4omJgj4EaAB0KnYl5VUDQ6NtNqqCk-N501KDwyN+aIHBYWgReZNlIP1SeeQjGVk5KHkA1PdVAL6nUhmIZChYwYLNH18fkIAGo0Ri8FCTCDdNTJMgZADmUAAPgU4mI1pJiM0NqNxkISsVSriRitFt0oF9BLwyPwoAAiACiZBMZA0iGy-FM6RygN+0g4B0sZLs9MxUBJ+ME92KAO+v1B4JYZ0kVJpdMlixeb0keBQn3lQmavXFmrsMBg2qqXwOfxNKolszGi2Opqd212oXCkUWj21r1YNWS2AAnhciqV+CgAO7cRbkZoAVm6gdq1QmpSwYfjZGddhA4AACiZ6ORBCGoAByEVCSvpTDGUz6ixQbKWGqMCs0ZDoNAEeSQ6MEDZ0tiCqvhutt9KCTBoORjjDoEZgUBZ8Ok9oui0APigjJCIQA8iEC6BizhS2Ry1WPUEvba8nXhtJ4Z5vNOO12exh+8woEOI7KOwnCVpOIzNAATAAzAALNCq7rjmWwBPe+yHNuMB7gex6nquWSCGkPyFJguiMDUSKCDgjqQoumDDgcjBEKmwbXCktxHKUG5sdkuRaqukGwFAhY0GQdARCIjZXoR6CsCBmCFuQaA1BiiQqLU9SNC0MjyGk-DiRocKIgANNIcgKEoNAIignSFL0rwBupwZXspdKRjGwlKTUzT0vAFkoPSpnQWU3QGE5ODMCM5EIs0Lk1CM+k-KFUDgAyfmKAFLERSgUU4DFcX8CMVkoMlKWgFAwUFgAVKugyQjQsg4O4tHyfW1QMAQzCWFRGggHRnkUCpfRmbpSiJTZSR1IiCQjRZrbWbZcSVJITl1A0VEtONhlTfwCKmcVi09Kp6xOuNkzjXokipdQTCKMOra-gi-BAoIVQksVkzFTNDkgFVoAgKu0FCVwXypLt1RCGJ5ikRE0b3sBgroK2-CWBkwhkEQ3ZIyAaPkJjqBQAAyn4pbHZIfYAF4TY4S1VCo5FspN8K7QYAa4xjWNQAAshENB4F4NBk8ooMWPA+QACJeCgrN9a1hMAI68KJkIEAwzAvZgxM0KWpk8yk-MpELlPU108R0xFTTbczCIzStIsoHgYsaJLwjLVIq2aRtzTG4dZCmfTltMyZwsoFLjsS1L9oqiSxuTMbtv9JqDOTAHZsOpK9vhynmdiwnP2rrBQkNXC3ZLAA1igIbRk0eBnsXdSlwjS6YBydJYAQVBQI1gytrIJfmMjljqQa3g-IM+CjMA9dQ0s-UXng61C9PjfWYIxYZcaag084iTLwPq-i+gnwEPQhHeTCQcszqZXD1SkJjz4+BQFUq+ExtKDGsNZxqrSVZcxWyQmgoErP6WW44wh4HFjaSgVBhAowUiYBeA9xBVHABkHw5AGLYAiI-Swr937X1XuvVAn9xQ-zpLBE4iQAyJAPkfeEp8CDny-v0chVYIFQDwNAqARAmjVEQGXFInUBTXlIGgEB1DgABhYksLMECoG9nOh5eR0DjRhSDNlXKMU5EOwURgEY+CgHGmSuAek-9JpAPpM-cKkVoqtBDCo3sBiIjEI-t0CkqVKHWI0bYvK9jHH6LoWgY+jDz4eNAPSDhXDFG8KKCoARQjGAiJkmgKxQA" rel="noopener noreferrer"&gt;TypeScript playground&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  1 - Access modifiers
&lt;/h3&gt;

&lt;p&gt;TypeScript introduced access modifiers for better control over class properties and methods. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;public:&lt;/strong&gt; used for properties that can be accessed inside the class, from instances of the class, and outside the class. By default, all class members are public in TypeScript if no access modifier is specified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;protected:&lt;/strong&gt; used for properties that can only be accessed within the class and by subclasses, but not from outside instances of the class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;private:&lt;/strong&gt; used for properties that can only be accessed within the class where they are defined and not by subclasses.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;maxCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;hasBeenResetCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;maxCount&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasBeenResetCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: cannot increment passed maxCount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasBeenResetCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;myCounter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myCounter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;

&lt;span class="c1"&gt;//Property 'maxCount' is protected and only accessible within class 'Counter' and its subclasses.&lt;/span&gt;
&lt;span class="c1"&gt;//myCounter.maxCount --&amp;gt; ERROR&lt;/span&gt;

&lt;span class="c1"&gt;//Property 'hasBeenResetCount' is private and only accessible within class 'Counter'.(2341)&lt;/span&gt;
&lt;span class="c1"&gt;//myCounter.hasBeenResetCount --&amp;gt; ERROR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2 - Parameter properties
&lt;/h3&gt;

&lt;p&gt;TypeScript provides a shorthand for automatically declaring and initializing class properties in the constructor, which JavaScript does not have. Note that you have to use access modifiers to explicitly declare the parameters in the constructor as class properties; otherwise, you will get an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Audrey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Audrey"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3 - Creating contracts between classes and interfaces
&lt;/h3&gt;

&lt;p&gt;TypeScript allows you to use interfaces to define contracts for classes. Interfaces promote loose coupling by separating the contract (interface) from its implementation (class). Implementing an interface doesn't provide any code to the class (unlike inheritance between classes); it only ensures that the class conforms to the contract, meaning the required methods and properties must be present. A class can implement multiple interfaces, allowing for more flexible design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4 - The abstract keyword
&lt;/h3&gt;

&lt;p&gt;TypeScript allows you to define abstract classes and methods, providing a way to enforce a structure similar to interfaces but with additional functionality.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Abstract classes&lt;/strong&gt; serve as blueprints for other classes. They cannot be instantiated directly (you cannot create an object of an abstract class).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An &lt;strong&gt;abstract method&lt;/strong&gt; is a method defined in an abstract class without a body (implementation). It forces any derived class to implement that method. Abstract methods are like placeholders—they define the signature of the method but leave the implementation details to the subclasses.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;getDescription&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;//concrete method &lt;/span&gt;
    &lt;span class="nf"&gt;getStore&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RedDress&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//inherits method getStore&lt;/span&gt;
   &lt;span class="c1"&gt;//implements abstract methods &lt;/span&gt;

    &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;getDescription&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Red dress for cocktail parties&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRedDress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedDress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;myRedDress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;//"My store" &lt;/span&gt;
&lt;span class="nx"&gt;myRedDress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// 40 &lt;/span&gt;
&lt;span class="nx"&gt;myRedDress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDescription&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;//"Red dress for cocktail parties" &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope this was helpful! &lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>ts</category>
    </item>
    <item>
      <title>🛠️ 📦 TypeScript Generics - a cheat sheet</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Thu, 15 Aug 2024 16:17:19 +0000</pubDate>
      <link>https://dev.to/audreyk/typescript-generics-a-cheat-sheet-1a89</link>
      <guid>https://dev.to/audreyk/typescript-generics-a-cheat-sheet-1a89</guid>
      <description>&lt;p&gt;Generics in TypeScript can seem daunting at first - what’s with all those capital letters and square brackets? 😅&lt;/p&gt;

&lt;p&gt;But don’t worry, this cheat sheet helps demystify Generics and show you how they work with simple examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Generics Works
&lt;/h2&gt;

&lt;p&gt;Generics enable you to define a type variable that serves as a placeholder for a specific type to be provided later. This is the core strength of Generics: they allow you to define flexible, reusable types without sacrificing type safety.&lt;/p&gt;

&lt;p&gt;The letter T is commonly used by convention to represent a generic type variable, but you can use any letter or descriptive name that fits your context (other commonly used letters include U, V, K).&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage examples
&lt;/h2&gt;

&lt;p&gt;Below are some practical examples that demonstrate how Generics work. &lt;/p&gt;

&lt;p&gt;You can play with the examples below in this &lt;a href="https://www.typescriptlang.org/play/?#code/PTDiFMDtwJwSwMYAIBmBXSCAucD2kAodTHfJOAEyhywE8AeAFQD4AKAQxgHMAuJRgJR9GSAN4EkkpDHBY0MSEk5cA3AQC+BAgBtZSSGgC2SALzkqkGgwOGARrDYAWAEwCVSEP3IBnfUfswOnreWDCm5tRwdPQh8JBcbABEABLg2tq4iW4ewF5wvrFw8VogENDwyEVYsCjsCOBIBFU1dQ0ACuxwMEwANEgA0sxiEqhdIcJqkt7gCPgUfP1qmkFYSAAOnTB8HV0xoUVcfTYBQ2aiozDjSIn44Il907OQ80jOSMulULCISHRr4AQ-u1YN58L0Bn0AGqnYaSSDsQzgYQ9EbsLhIiEjfIAWU48HAL0hGi0TxC6xB+AAjNsKZA9nFDn47LA+rZcLhdOxIDDxHCERiAOQAIVwtgFKMkaIxADYAOwSny4mD4l61bTTYkET7lRC+IpIBDadjebwEQ3G3wigAeTCGvIN+GqlmEWkkpNCaGwuBgrCeTqwwgE9skWAAFvkAHR+6jhaOWEbLSTorAAYUd1FYQi8weksnkijDkbjWATmvdSF0WGqMGt4WgAHckNbWAL2AKBGb8GTjrBa2YG03cFbWJSO1rgO6YJ1LKagUgADJQLhhxi0f7hUS6eJhvg9mCaYjYPCKZOL7ehphIcBWp0UXxn5eh1f-NjKbyB+0yOQKJTcbwRrdH01U8lzDFt2FsBB2wIEDz1YABtSk+mcABdMcQELXwKFwcBvEgAVVnrb0AGtxwAQW4IwY1wFBfjXBoBT3AUfH0XBVgtOAuHhWxdF+XB1k4flqyQGi6PXAUHxXeiBXHWDH1YABWMcgA" rel="noopener noreferrer"&gt;TypeScript playground&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generics Functions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A generic function that works with any data type&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Using the generic function with different types&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// T is number&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// T is string&lt;/span&gt;

&lt;span class="c1"&gt;//TS automatically infers the type so this also works:&lt;/span&gt;
&lt;span class="c1"&gt;//let num = identity(42); // T is number&lt;/span&gt;
&lt;span class="c1"&gt;//let str = identity("Hello"); // T is string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, T is a type parameter that can represent any type. The actual type is determined when the function is called, whether it’s a number, string, or any other type.&lt;/p&gt;

&lt;p&gt;Here, we've manually set the type to highlight how TypeScript handles different types with generics. However, it's important to remember that TypeScript typically infers the type automatically based on the argument provided. You don't need to manually specify the type unless you're overriding TypeScript's inference or dealing with complex types where explicit type annotations are necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic Interfaces
&lt;/h3&gt;

&lt;p&gt;Here, we define an interface Pair with two properties of different types. These types are specified when an instance is created and can be any type. The only constraint is that each property maintains its respective type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anotherPair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;second&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;otherPair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generics Types
&lt;/h3&gt;

&lt;p&gt;Generics can also be applied to custom types. The process is similar to interfaces: you define a shape with placeholder types, which are determined when the type is used. Generics enforce typing but do not dictate specific types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isMarried&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;V&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isMarried&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generic Classes
&lt;/h3&gt;

&lt;p&gt;Generic classes allow you to define a blueprint where the data’s type is flexible, only being defined when an instance is created. In this example, the Box class can store content of any type (for example, a string, a number, or any other type).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;letterBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Constraints
&lt;/h3&gt;

&lt;p&gt;Generics also support constraints, allowing you to limit the types that can be used. For example, if you only want to support types with a length property, you can enforce this constraint using the extends keyword. It restricts the generic type variable to be a subtype of a particular type or interface. This ensures that the generic type must have certain properties or structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LengthType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getLength&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;LengthType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;getLength&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;//this doesn't work:&lt;/span&gt;
&lt;span class="c1"&gt;//getLength(2)&lt;/span&gt;
&lt;span class="c1"&gt;//getLength({"a": "b"})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Utility types
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html" rel="noopener noreferrer"&gt;Utility types&lt;/a&gt; in TypeScript use generics to create flexible and reusable type transformations. They simplify working with existing types by providing built-in operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//makes all properties optional &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;partialUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//allows to omit properties: here the name property is omitted&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;omitUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Berlin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope this was helpful! &lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>ts</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>☁️ 🥇 Tips and free resources for passing the AWS Developer Associate Certification</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Sun, 28 Jul 2024 11:39:22 +0000</pubDate>
      <link>https://dev.to/audreyk/tips-and-free-resources-for-passing-the-aws-developer-associate-certification-2il6</link>
      <guid>https://dev.to/audreyk/tips-and-free-resources-for-passing-the-aws-developer-associate-certification-2il6</guid>
      <description>&lt;p&gt;A few months ago, I successfully passed the AWS Developer Associate certification. Here are some tips for preparing for and taking the exam!&lt;/p&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;Here is a list of resources I used to prepare for the exam:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource Name&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official AWS Certification Information and Policies&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;&lt;a href="https://aws.amazon.com/certification/policies/?nc1=h_ls" rel="noopener noreferrer"&gt;AWS Certification Information&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Official AWS Sample Questions&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;&lt;a href="https://d1.awsstatic.com/training-and-certification/docs-dev-associate/AWS-Certified-Developer-Associate_Sample-Questions.pdf" rel="noopener noreferrer"&gt;Official Mock Questions&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Free Practice Test Questions GitHub Repo&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Ditectrev/Amazon-Web-Services-AWS-Developer-Associate-DVA-C02-Practice-Tests-Exams-Questions-Answers" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Bites Podcast&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;&lt;a href="https://awsbites.com/" rel="noopener noreferrer"&gt;AWS Bites Podcast&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tutorials Dojo&lt;/td&gt;
&lt;td&gt;$14.99&lt;/td&gt;
&lt;td&gt;&lt;a href="https://portal.tutorialsdojo.com/courses/aws-certified-developer-associate-practice-exams/" rel="noopener noreferrer"&gt;Tutorials Dojo&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Cloud Guru&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pluralsight.com/cloud-guru/courses/aws-certified-developer-associate-dva-c02" rel="noopener noreferrer"&gt;A Cloud Guru&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It took me about 2.5 months to prepare for the exam. I used &lt;a href="https://www.pluralsight.com/cloud-guru/courses/aws-certified-developer-associate-dva-c02" rel="noopener noreferrer"&gt;A Cloud Guru's training&lt;/a&gt; and tried to study for at least 1 hour every day and 2-3 hours on the weekends. I like A Cloud Guru because it's a good mix of theoretical and hands-on training: they give you test accounts so you can practice on the real AWS console without using your personal account (and risk getting charged!). (I have no affiliation with A Cloud Guru!).&lt;/p&gt;

&lt;p&gt;In my opinion, it is important to get as much hands-on experience as possible to understand how the services work and how to apply them to real-world scenarios. The exam includes scenario-based questions, so this is important. An in-depth understanding of the main services (including EC2, Lambda, API Gateway, S3, DynamoDB, CloudFront, Systems Manager Parameter Store, Secrets Manager, SQS) and how they work together is essential.&lt;/p&gt;

&lt;p&gt;To deepen my knowledge, I listened to the &lt;a href="https://awsbites.com/" rel="noopener noreferrer"&gt;AWS Bites&lt;/a&gt; podcast in my spare time, especially the episodes on Serverless, S3, Lambda, Cognito, and DynamoDB. The episodes are short and of good quality. I enjoyed listening to them and would definitely recommend the podcast.&lt;/p&gt;

&lt;p&gt;When I finished A Cloud Guru's course, I took all of their sample exams. After each exam, I reviewed the questions I got wrong. A Cloud Guru gives you an explanation for each answer, so it is easy to see why you got it wrong.&lt;/p&gt;

&lt;p&gt;As my exam date approached, I almost panicked when I checked &lt;a href="https://www.reddit.com/r/AWSCertifications/comments/pfwouu/avoid_acloudguru/" rel="noopener noreferrer"&gt;reddit and people said that preparing with A Cloud Guru wasn't enough&lt;/a&gt; and recommended &lt;a href="https://portal.tutorialsdojo.com/courses/aws-certified-developer-associate-practice-exams/" rel="noopener noreferrer"&gt;Tutorials Dojo&lt;/a&gt;'s sample exams. I bought &lt;a href="https://portal.tutorialsdojo.com/courses/aws-certified-developer-associate-practice-exams/" rel="noopener noreferrer"&gt;Tutorials Dojo&lt;/a&gt; and took a few. They are harder than the real exam, so don't be afraid if you score lower on them. They also have good in-depth explanations of the answers to the questions, so it's good to supplement your preparation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The exam
&lt;/h3&gt;

&lt;p&gt;I took the exam online with &lt;a href="https://home.pearsonvue.com/Clients/AWS.aspx" rel="noopener noreferrer"&gt;Pearson VUE&lt;/a&gt;. The experience was smooth, and I didn't have any problems. There is a check at the beginning, so before the exam, clear the room of any posters or unnecessary items. Just leave your computer on the table.&lt;/p&gt;

&lt;p&gt;As for the exam itself, most of the questions are scenario-based, and you have multiple choices. It's important to read each question carefully, but don't overthink it. Try to understand the scenario and the problem, and then eliminate the choices that you are sure are incorrect. If you don't know the answer, use common sense. Try all the questions because there are no negative marks. There was a big focus on Serverless in my exam, and many questions revolved around Lambda, API Gateway, CloudFront, S3, and DynamoDB.&lt;/p&gt;




&lt;p&gt;I hope this guide was helpful! Good luck on the exam! You can do it!&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>webdev</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>🧭 🇹 When to use the non-null assertion operator in TypeScript</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Wed, 17 Jul 2024 16:11:12 +0000</pubDate>
      <link>https://dev.to/audreyk/when-to-use-the-non-null-assertion-operator-in-typescript-545f</link>
      <guid>https://dev.to/audreyk/when-to-use-the-non-null-assertion-operator-in-typescript-545f</guid>
      <description>&lt;p&gt;Did you know that TypeScript has a &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator" rel="noopener noreferrer"&gt;non-null assertion operator&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;The non-null assertion operator (!) is used to assert that a value is neither null nor undefined. It tells TypeScript's type checker to ignore the possibility that the value is null or undefined, thus bypassing type checking for these values.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to use it
&lt;/h2&gt;

&lt;p&gt;Use the non-null assertion operator when you are certain that a variable will be assigned a non-null value when you access it (for example, after a type guard).&lt;/p&gt;

&lt;p&gt;In the example below, we use a non-null assertion operator (at &lt;code&gt;user.email!&lt;/code&gt;) because we're certain that the value of the email property exists. Even though email is defined as an optional value in the User interface, we're checking for its existence with a type guard in the getEmail function, so we can be sure that it exists.&lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA2AfnacejAL65cMCiARhgAexDJuEMAFFBIgBQVMUMhmgBKEhy4huOOYRgGAhMegA6AUOEXkUbQooDQByADkAegBBELkIiJBVFSRkMAALODBkABUATwAHCABlBC58rIB3VQphInIk1LSoVQrkOA1oZqgnZAqUAKpVADcIOvSURJAAWkphYTb0ExV1ZFVCqEzVKA9kJgCwII13be8RFxk5XAR1DmRjsxNkAF4cQlJkAEYAGmZWMhCosJgEgQj9TsIyAAiOBApAAAXBHmuVEh0kY1xAt3Bz002j0PiMJgs6JuqmEEA8wlU3AMAANzFAQuhkOCyAASbDg6S04mOZBAA" rel="noopener noreferrer"&gt;check this example in the TypeScript Playground&lt;/a&gt; and play with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;N/A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alice@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User's email: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice in this example that TypeScript would not throw an error if we removed the non-null assertion operator. &lt;/p&gt;

&lt;p&gt;In TypeScript, while accessing optional properties like email without the non-null assertion operator is allowed, adding the non-null assertion operator can assert your understanding that the property is indeed present when accessed. This can be helpful for clarity and documentation, especially in large codebases or when working in teams. It also prevents TypeScript from warning you about potentially undefined values and allows you to treat the property as if it is always present, avoiding unnecessary runtime checks.&lt;/p&gt;




&lt;p&gt;Hope this article has clarified the use of the intriguing non-null assertion operator in TypeScript!&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>📋 📝 Manage your clipboard in the CLI with Python</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Mon, 01 Jul 2024 07:48:37 +0000</pubDate>
      <link>https://dev.to/audreyk/manage-your-clipboard-in-the-cli-with-python-5f0d</link>
      <guid>https://dev.to/audreyk/manage-your-clipboard-in-the-cli-with-python-5f0d</guid>
      <description>&lt;p&gt;As someone who frequently copies and pastes content, I've often wondered about the inner workings of the clipboard and whether it was possible to manage it programmatically. I ended up writing a simple Python script that allows you to get the current value in the clipboard, clear it, and get its history via the command line interface (CLI).&lt;/p&gt;




&lt;h2&gt;
  
  
  How it Works
&lt;/h2&gt;

&lt;p&gt;Here is a step-by-step guide to implementing this functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Define a ClipboardManager class&lt;/strong&gt;: 
The first step is to define a &lt;code&gt;ClipboardManager&lt;/code&gt; class. This class will serve as the foundation for managing clipboard operations within the script. The &lt;code&gt;__init__&lt;/code&gt; method is the constructor: it sets up the initial state of the object when it is created. In this example, &lt;code&gt;__init__&lt;/code&gt; initializes &lt;code&gt;history&lt;/code&gt; as an empty list and &lt;code&gt;current_value&lt;/code&gt; as None.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClipboardManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Implement get clipboard and clear clipboard methods&lt;/strong&gt;:
Using the &lt;a href="https://pypi.org/project/pyperclip/" rel="noopener noreferrer"&gt;pyperclip&lt;/a&gt; module, we define methods within the &lt;code&gt;ClipboardManager&lt;/code&gt; class to interact with the clipboard. These methods allow fetching the current clipboard value and clearing the clipboard. Every time we get the current clipboard value, we add it in the history list to keep track of it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;       &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_clipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear_clipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Clipboard cleared.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Implement the show history method&lt;/strong&gt;:
Next, we need to include a method that displays the history of clipboard values stored in &lt;code&gt;self.history&lt;/code&gt;. In this method, we loop through the items in the list and use the &lt;a href="https://docs.python.org/3/library/functions.html#enumerate" rel="noopener noreferrer"&gt;enumerate built-in function&lt;/a&gt; to pair each value with an index, producing a numbered list. We set the starting index to 1 to make the output more user-friendly, aligning with the human convention of counting from 1, unlike computers which typically start counting from 0.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No history available.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instantiate the class and provide options in the CLI&lt;/strong&gt;:
The last step is to implement the main execution logic of the script. We instantiate an object of &lt;code&gt;ClipboardManager&lt;/code&gt; and create a user-friendly menu in the command-line interface to allow users to perform operations on the clipboard.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClipboardManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Menu:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1. Get current clipboard value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2. Show clipboard history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3. Clear clipboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4. Exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter your choice (1-4): &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_clipboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Current clipboard value: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show_history&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear_clipboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Exiting...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid choice. Please enter a number from 1 to 4.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the final script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pyperclip&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClipboardManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_clipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paste&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No history available.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear_clipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;pyperclip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Clipboard cleared.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClipboardManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Menu:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1. Get current clipboard value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2. Show clipboard history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3. Clear clipboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4. Exit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter your choice (1-4): &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;current_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_clipboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Current clipboard value: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show_history&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear_clipboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Exiting...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid choice. Please enter a number from 1 to 4.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;To utilize this script, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Save the script into a file with a .py extension (e.g., clipboard-script.py).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a terminal and navigate to the directory containing the script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the script by providing the script path. For example:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &amp;lt;script-path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 clipboard-script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can test the script by copying text from your command-line interface (CLI) and begin utilizing its functionality to manage clipboard operations effectively.✨&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>productivity</category>
      <category>clipboard</category>
    </item>
    <item>
      <title>📁🐍 Automate File Renaming with Python</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Wed, 06 Mar 2024 17:48:59 +0000</pubDate>
      <link>https://dev.to/audreyk/automate-file-renaming-with-python-5k</link>
      <guid>https://dev.to/audreyk/automate-file-renaming-with-python-5k</guid>
      <description>&lt;p&gt;Renaming files can be a tedious task, especially if you have many. Last time I was sorting through my photos and found myself renaming them one by one, I decided to automate the task 👩🏻‍🔬&lt;/p&gt;




&lt;h2&gt;
  
  
  How it Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input Validation&lt;/strong&gt;: The script begins by checking if the required arguments are provided via command-line input. If not, it prompts the user to provide the folder path and the new name for the files. The &lt;a href="https://docs.python.org/3/library/sys.html" rel="noopener noreferrer"&gt;sys module&lt;/a&gt; is used to extract the command-line input.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Enumeration&lt;/strong&gt;: It then lists all the files in the specified folder. The script will iterate through all the eligible files in the folder, renaming them sequentially. The &lt;a href="https://docs.python.org/3/library/os.html" rel="noopener noreferrer"&gt;os module&lt;/a&gt; is used for file-related operations. A regular expression (&lt;code&gt;file_extension_pattern&lt;/code&gt; variable) is defined using the &lt;a href="https://docs.python.org/3/library/re.html" rel="noopener noreferrer"&gt;re module&lt;/a&gt;. Its role is to match the file extension (eg. &lt;code&gt;.png&lt;/code&gt; for a file named &lt;code&gt;image.png&lt;/code&gt;).&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Renaming Process&lt;/strong&gt;: For each file with an image extension (e.g., JPEG, PNG), the script extracts the file extension using the regular expression pattern, generates a new name, and renames the file accordingly. The new name is formed by concatenating the name, an underscore _, and the count. For example, if the user provides &lt;code&gt;image&lt;/code&gt; as the new name and the script processes 3 files, the new names would be: &lt;code&gt;image_1&lt;/code&gt;, &lt;code&gt;image_2&lt;/code&gt;, &lt;code&gt;image_3&lt;/code&gt;. Feel free to adjust this pattern based on your needs.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Please provide a folder path and a new name.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;image_extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tiff&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;base_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;file_extension_pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\.[^.]+$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_extensions&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_extension_pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;new_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;old_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;
        &lt;span class="n"&gt;new_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base_path&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;new_name&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;file_extension&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;To utilize this script, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Save the script into a file with a .py extension (e.g., rename_files.py).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a terminal or command prompt and navigate to the directory containing the script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the script by providing the folder path and the desired new name as command-line arguments. For example:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &amp;lt;script&amp;gt; &amp;lt;path&amp;gt; &amp;lt;new_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 rename_files.py /path/to/folder new_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! All your files should be automatically renamed ✨&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions! You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>👩‍💻🏆 5 tips for surviving (and winning!) a Hackathon</title>
      <dc:creator>Audrey Kadjar</dc:creator>
      <pubDate>Tue, 16 Jan 2024 07:24:00 +0000</pubDate>
      <link>https://dev.to/audreyk/5-tips-for-surviving-and-winning-a-hackathon-3bfm</link>
      <guid>https://dev.to/audreyk/5-tips-for-surviving-and-winning-a-hackathon-3bfm</guid>
      <description>&lt;p&gt;I recently participated in my third Hackathon (&lt;a href="https://germany.girlsintech.org/empowering-berlin-flinta-tech-community-hackathon/" rel="noopener noreferrer"&gt;Hack for Impact&lt;/a&gt; in Berlin co-organized by Google, On, Adesso, Girls in Tech) and had so much fun! With my team, we developed an AI-powered app that allows users to scan the tags on their clothes to discover their sustainable impact. It was fun to develop a project from start to finish and see everyone's final pitches. In the end, we even won first prize for our project! 🏆&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Hackathon" rel="noopener noreferrer"&gt;Hackathons&lt;/a&gt; are great opportunities to meet people and build innovative projects. Creating an entire project in a tight timeframe also shows you the incredible things you can accomplish with focused effort. Here are my 5 tips!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqstgn3hbgeg5amdlrev.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqstgn3hbgeg5amdlrev.jpeg" alt="Image description" width="800" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding a Hackathon
&lt;/h2&gt;

&lt;p&gt;Before you dive in, research and choose a hackathon that matches your skills and interests. For example, don't sign up for a hackathon for Machine Learning engineers if you lack ML skills. Also, consider the tone and topics of the event to make sure they match your personality and interests. Check out events hosted by tech meetups and organizations. &lt;a href="https://devpost.com/hackathons" rel="noopener noreferrer"&gt;Devpost&lt;/a&gt; is also a great resource for finding Hackathons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up your work environment
&lt;/h2&gt;

&lt;p&gt;To save valuable time during the event, prepare your work environment ahead of time. Configure your IDE, install necessary packages, and set up boilerplate code. At my last Hackathon, I set up the project's boilerplate (a minimal Node.js backend with a PostgreSQL database along with a React frontend) before the event, which allowed us to focus on our project when the hackathon started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a diverse team
&lt;/h2&gt;

&lt;p&gt;Whether you sign up with a pre-formed team or team up with participants on the day of the hackathon, make diversity of skills a priority. At my last hackathon, our winning team met on the day of the event and had a balanced mix of 1 backend, 2 frontend, 1 UI designer, 1 UX designer, and 1 project manager. This diversity proved critical to our success, as each team member brought a unique contribution to the project. &lt;/p&gt;

&lt;h2&gt;
  
  
  Develop an innovative, feasible idea
&lt;/h2&gt;

&lt;p&gt;At the beginning of the Hackathon, spend time brainstorming and selecting an idea. The challenge is to come up with an idea that's both innovative and feasible within the limited time frame. Give each team member room to contribute, and do your research to make sure your concept doesn't replicate existing applications. Focus on implementing 2 or 3 features well, rather than trying to implement 10 half-baked features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prioritize presentation and pitching
&lt;/h2&gt;

&lt;p&gt;Don't underestimate the importance of a well-prepared presentation. During my first Hackathon, with my team we were so focused on coding that we only had 1 hour left to build the presentation, which led to a rushed pitch 😵 Make sure you spend enough time preparing the presentation and rehearsing the pitch (I recommend 2-3 hours). Showcase your process and your idea's unique selling point, and include engaging demos of your key features.&lt;/p&gt;




&lt;p&gt;Good luck and have fun at your next Hackathon! Feel free to share your tips and Hackathon experiences in the comments ⭐&lt;/p&gt;

&lt;p&gt;You can also find me on &lt;a href="https://github.com/AudreyKj" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/audreykadjar/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://www.instagram.com/audreykadjar/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>tips</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
