<?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: Sachit</title>
    <description>The latest articles on DEV Community by Sachit (@sachitsac).</description>
    <link>https://dev.to/sachitsac</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%2F707369%2Fc77fe16f-93fb-4718-9b73-9867eef1d4f8.png</url>
      <title>DEV Community: Sachit</title>
      <link>https://dev.to/sachitsac</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sachitsac"/>
    <language>en</language>
    <item>
      <title>Are custom decentralised app the future?</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Tue, 23 Dec 2025 13:18:31 +0000</pubDate>
      <link>https://dev.to/sachitsac/bookmarkify-sportify-podcasts-2dff</link>
      <guid>https://dev.to/sachitsac/bookmarkify-sportify-podcasts-2dff</guid>
      <description>&lt;p&gt;Building custom apps are not easy, they are expensive and they take a lot of time to build. It requires team of people to interpret the problems and find solutions for not just one use case but most often generic enough that others can also find it useful.&lt;/p&gt;

&lt;p&gt;Every app I've used, has had the same problems that I've experienced. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The app have a long onboarding process.&lt;/li&gt;
&lt;li&gt;The app needs a lot of data before it starts becoming useful.&lt;/li&gt;
&lt;li&gt;The app needs to have friends or community for it to be useful.&lt;/li&gt;
&lt;li&gt;The app is bloated and slow and 80% of the features are useless to me.&lt;/li&gt;
&lt;li&gt;The app is generic and I have to fit my workflow or my process into how the app want's me to, which is backward and not natural.&lt;/li&gt;
&lt;li&gt;The app requires me to pay for features that I don't need.&lt;/li&gt;
&lt;li&gt;The app requires a subscription and its cheaper to buy an annual subscription than monthly.&lt;/li&gt;
&lt;li&gt;The app shows me ads that only distracts me from doing what I need to and some apps give options to be a paid customer to remove ads but charge an arm and a leg for the privilege.&lt;/li&gt;
&lt;li&gt;They want data that has no requirement for the app, e.g. location or microphone etc. just so that they can collect and sell that data to brokers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many more but i don't want to go on and on ...&lt;/p&gt;

&lt;p&gt;This has got me thinking, with the advancements in technology specially Artificial Intelligence, Machine leaning and Large language models that are for even becoming smarter and better at coding, why can't we build tailored custom apps that can run securely on the user's computers or hosted by them securely in the cloud ? They control the data and privacy, they only get features they need and no bloat or ads that get in the way and not to mention the keeping you hooked for longer hours that will only make us do things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not spending time with family or friends.&lt;/li&gt;
&lt;li&gt;Not having time to exercise or staying healthy.&lt;/li&gt;
&lt;li&gt;Not having time to cook and having take out food using apps like Uber eats and pay higher amount to have the same meal that they can either by going to the restaurant or picking up the food themself ?&lt;/li&gt;
&lt;li&gt;and many more ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now admittedly, I've been building apps for almost two decades and I am very comfortable with building apps that are secure and privacy aware. Operating systems vendors like Apple, Microsoft, and Linux can be the platforms that allow users to build custom tailored applications: Nothing more, nothing less that runs on their infrastructure so that the user can have the peace of mind and focus on just building out a solution for their very specific problem and their way of solving it for what will work for them.&lt;/p&gt;

&lt;p&gt;I'm starting on this journey on building apps for my problems. Along the way I will try and figure out how this can scale to other users that might not be as technology versed or aware as someone like myself who has relevant industry experience.&lt;/p&gt;

&lt;p&gt;Here's an example of an app that is very specific to my needs, a very simple fitness tracker. This is built using Claude Opus 4.5 and claude code. It's very specific to what my fitness goals are and any feature in this application thus far is what I need, nothing more, nothing less. I will build on this and improve the application as my needs or requirements progress. And I don't need to share this data with anyone, everything stays on my computer, in my control, safe and sound. &lt;/p&gt;

&lt;p&gt;This is in a way a decentralised application. If a hacker wants to get this data, they will have to hack my computer which takes a lot of time and effort. If they have to do it for every single user in the world, it will be a very expensive exercise on their part to do this which makes it's not as viable as attacking a central server where a lot of data is stored is a lot more attractive.&lt;/p&gt;

&lt;p&gt;Here's the app: Its not hosted anywhere, it sits on my computer, is available to me locally on any of my devices and is hosted within my private network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtube.com/shorts/P2r1RjLv154?feature=share" rel="noopener noreferrer"&gt;My Custom Fitness App&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would encourage everyone to learn this technology and not be fearful of the future that this promises. Centralisation and DecentraliSation both have their advantages and disadvantages so by no means is this the solution that will solve all the problems in the world, but at least it will give the user the power of using or creating solutions to their problems in the way that really works for how they think and how they work. If you have a question on how I've built this, feel free to leave a comment and I'm happy to share how I've built this so that you can be on the same journey as I am.&lt;/p&gt;

&lt;p&gt;Start local to mitigate any risks of your data being exposed or sensitive information getting in the hands of people. Once the infrastructure catches up with this idea, I'm hopeful that those things will not be something a user will have to think about. Eventually they will only think about their problems and their solutions.&lt;/p&gt;

&lt;p&gt;Declaimer: This article is fully human written, no help from AI to write or polish this article, this is original human content.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>ai</category>
      <category>fitness</category>
    </item>
    <item>
      <title>How I Finally Solved My 500+ Bookmark Problem with AI</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Thu, 04 Sep 2025 13:39:50 +0000</pubDate>
      <link>https://dev.to/sachitsac/how-i-finally-solved-my-500-bookmark-problem-with-ai-39gf</link>
      <guid>https://dev.to/sachitsac/how-i-finally-solved-my-500-bookmark-problem-with-ai-39gf</guid>
      <description>&lt;p&gt;In our day-to-day work as developers, we save dozens of links - documentation, Stack Overflow answers, interesting blog posts, GitHub repos. But lets be honest, how often do we actually find and use these bookmarks again?&lt;/p&gt;

&lt;p&gt;Lets look at the problem first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You have hundreds or thousands of bookmarks scattered across browsers and devices. You need that one specific Stack Overflow answer about React hooks that you saved 6 months ago. You spend 15 minutes searching through nested folders, give up, and Google it again.&lt;/p&gt;

&lt;p&gt;So basically, our bookmark system is broken. Here's what typically happens:&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="c1"&gt;// How we think bookmarks work&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;savedBookmark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://important-article.com&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;Web Dev &amp;gt; React &amp;gt; Hooks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;accessibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Easy to find&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// How bookmarks actually work&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;realityBookmark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://important-article.com&lt;/span&gt;&lt;span class="dl"&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="s2"&gt;Misc? JavaScript? TODO? Who knows...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;accessibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastSeen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Never again&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;h2&gt;
  
  
  What Makes This Hard
&lt;/h2&gt;

&lt;p&gt;So i can already think of few issues with traditional bookmarks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We save links without context - three months later "Important!!!" means nothing&lt;/li&gt;
&lt;li&gt;Manual folder organization doesn't scale beyond 50 bookmarks&lt;/li&gt;
&lt;li&gt;Browser bookmarks are tied to single devices&lt;/li&gt;
&lt;li&gt;No way to search by content, only by title&lt;/li&gt;
&lt;li&gt;Dead links accumulate over time (30% of my bookmarks were 404s)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Technical Requirements
&lt;/h2&gt;

&lt;p&gt;For a bookmark system to actually work for developers, it needs:&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;IdealBookmarkManager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;organization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;automatic&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;ai-powered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;full-text&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;semantic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cross-device&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;visual-preview&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;summary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;maintenance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self-cleaning&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;h2&gt;
  
  
  Enter AI-Powered Organization
&lt;/h2&gt;

&lt;p&gt;After trying to build my own solution (classic developer move), i realized this was a solved problem - we just needed to apply AI to it properly.&lt;/p&gt;

&lt;p&gt;The key insight: &lt;strong&gt;AI can understand content and organize it better than we can manually&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lets look at how this works in practice. I've been testing &lt;a href="https://bookmarkify.app" rel="noopener noreferrer"&gt;Bookmarkify&lt;/a&gt;, an AI-powered bookmark manager, and here's what changed:&lt;/p&gt;

&lt;h3&gt;
  
  
  Before (Manual Process)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Find interesting article about TypeScript generics&lt;/li&gt;
&lt;li&gt;Spend 30 seconds deciding which folder&lt;/li&gt;
&lt;li&gt;Create new folder because it doesn't fit existing ones&lt;/li&gt;
&lt;li&gt;Save and forget where&lt;/li&gt;
&lt;li&gt;Never find it again&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  After (AI Process)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Save link&lt;/li&gt;
&lt;li&gt;AI reads content and auto-categorizes&lt;/li&gt;
&lt;li&gt;AI generates relevant tags&lt;/li&gt;
&lt;li&gt;Content becomes searchable&lt;/li&gt;
&lt;li&gt;Find it instantly with "typescript generics tutorial"&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Technical Implementation
&lt;/h2&gt;

&lt;p&gt;What makes this work is fairly straightforward:&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="c1"&gt;// Traditional bookmark&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Page Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/manually/created/path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// AI-enhanced bookmark&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Page Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&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;auto-generated&lt;/span&gt;&lt;span class="dl"&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;by-content-analysis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Determined by NLP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AI-generated excerpt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fullText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Searchable content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Visual screenshot&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;p&gt;The AI reads the actual content, understands what it's about, and organizes accordingly. No manual intervention needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Results After Using It
&lt;/h2&gt;

&lt;p&gt;After importing my 500+ bookmarks into Bookmarkify, here's what happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic cleanup&lt;/strong&gt;: Found and removed 150+ dead links&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate detection&lt;/strong&gt;: Merged 80+ duplicate saves&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-effort organization&lt;/strong&gt;: Everything categorized without any input from me&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actually using bookmarks&lt;/strong&gt;: From maybe 5% usage to about 40%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time saved&lt;/strong&gt;: ~45 minutes per week not searching for links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The visual cards feature is particularly useful - i can recognize articles by their preview images much faster than reading through text lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Features for Developers
&lt;/h2&gt;

&lt;p&gt;What's actually useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Import existing bookmarks&lt;/strong&gt;: Imported all my Chrome bookmarks, it organized them automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural language search&lt;/strong&gt;: Type "react performance optimization" and it finds everything related&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text-to-speech&lt;/strong&gt;: Listen to articles during commute&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant summaries&lt;/strong&gt;: Get the key points without reading entire articles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-device sync&lt;/strong&gt;: Same bookmarks on all devices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Migration Process
&lt;/h2&gt;

&lt;p&gt;If you're sitting on hundreds of unorganized bookmarks like i was:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export your bookmarks from your browser (usually HTML format)&lt;/li&gt;
&lt;li&gt;Import into Bookmarkify (accepts HTML and CSV formats)&lt;/li&gt;
&lt;li&gt;Let AI do the heavy lifting of categorization&lt;/li&gt;
&lt;li&gt;Review and use the search instead of browsing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole process took me about 10 minutes for 500+ bookmarks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Traditional bookmarks don't work because they require manual organization that we'll never maintain. AI-powered tools like &lt;a href="https://bookmarkify.app" rel="noopener noreferrer"&gt;Bookmarkify&lt;/a&gt; solve this by understanding content and organizing automatically.&lt;/p&gt;

&lt;p&gt;If you're drowning in bookmarks, its worth trying. They're in beta and accepting users - perfect time to influence the product direction with developer feedback.&lt;/p&gt;

&lt;p&gt;Until next time, happy bookmarking (the organized way)!&lt;/p&gt;

&lt;p&gt;PS: Would love to hear about your bookmark organization strategies (or lack thereof) in the comments.&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%2Fdcihd33q55lrhe2zwc4u.png" 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%2Fdcihd33q55lrhe2zwc4u.png" alt=" " width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>tooling</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Built a Pocket alternative - a bookmarking app - need your feedback!</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Mon, 01 Sep 2025 12:03:07 +0000</pubDate>
      <link>https://dev.to/sachitsac/built-a-pocket-alternative-with-ai-superpowers-need-your-feedback-50-lifetime-free-spots-2b29</link>
      <guid>https://dev.to/sachitsac/built-a-pocket-alternative-with-ai-superpowers-need-your-feedback-50-lifetime-free-spots-2b29</guid>
      <description>&lt;p&gt;Hey fellow devs,&lt;/p&gt;

&lt;p&gt;Like many of you, I was frustrated when Pocket shut down was announced. So I spent the last 6 weeks building &lt;a href="https://bookmarkify.app" rel="noopener noreferrer"&gt;Bookmarkify&lt;/a&gt; - but instead of just cloning Pocket, I added the features we actually need as developers.&lt;/p&gt;

&lt;p&gt;What I've built so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🤖 AI auto-tagging - Never manually organize again&lt;/li&gt;
&lt;li&gt;🔍 Smart search - Find bookmarks by content, not just titles&lt;/li&gt;
&lt;li&gt;📺 Native embeds - Watch YouTube videos, view code snippets, all in-app&lt;/li&gt;
&lt;li&gt;📖 Reader mode with AI - Summaries + text-to-speech for any article&lt;/li&gt;
&lt;li&gt;👁️ Rich previews - Visual grid/list views that actually help you find stuff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why I need you:&lt;/p&gt;

&lt;p&gt;I'm at the point where it's useful but needs real-world testing. Your feedback will directly shape what I build next.&lt;/p&gt;

&lt;p&gt;🎁 The deal: First 50 beta testers get lifetime access free forever (including all future premium features).&lt;/p&gt;

&lt;p&gt;I genuinely want to build this with the community, not just for it. What bookmark management problems drive you crazy?&lt;/p&gt;

&lt;p&gt;Join the beta: &lt;a href="https://bookmarkify.app" rel="noopener noreferrer"&gt;Bookmarkify&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tech stack i've used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typescript&lt;/li&gt;
&lt;li&gt;Nextjs&lt;/li&gt;
&lt;li&gt;Supabase Auth and database&lt;/li&gt;
&lt;li&gt;OpenRouter to use some AI models&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask me how i've used Claude Code to build this, its been an amazing journey thus far building AI assisted products.&lt;/p&gt;

&lt;p&gt;Looking forward to your thoughts!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>news</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Building my own ChatGPT</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Sat, 25 May 2024 16:16:27 +0000</pubDate>
      <link>https://dev.to/sachitsac/building-my-own-chatgpt-3aid</link>
      <guid>https://dev.to/sachitsac/building-my-own-chatgpt-3aid</guid>
      <description>&lt;p&gt;I was watching a YouTube tutorial, and the speaker mentioned that you don’t need to subscribe to the ChatGPT monthly plan. Instead, you can use their API directly, which is cheaper. That got me thinking: how easy would it be to build my own ChatGPT with the option of using locally hosted models like Ollama 3?&lt;/p&gt;

&lt;p&gt;Today, we’re taking a quick dive into building a simple ChatGPT clone using some cool tech:&lt;/p&gt;

&lt;p&gt;Our Tech Stack&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Nextjs&lt;/a&gt;: This React meta framework is perfect for building fast, scalable web apps with features like server-side rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;: Adding types to JavaScript makes your code more reliable and easier to maintain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;ShadCN/UI&lt;/a&gt;: Helps us build beautiful, responsive user interfaces, fast and easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sdk.vercel.ai/docs/introduction" rel="noopener noreferrer"&gt;Vercel AI SDK&lt;/a&gt;: Simplifies connecting our app to OpenAI's GPT-4, making it easy to work with AI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenAI GPT-4o: The star of the show, GPT-4 can generate human-like text and is super versatile.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;: User authentication made for developers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/remarkjs/react-markdown" rel="noopener noreferrer"&gt;React-Markdown&lt;/a&gt;: Renders Markdown content in our React app, making text display neat and user-friendly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a little sneak peek of where I am so far. In the coming posts, I’ll share the code and instructions on how it was built. The chosen tech stack makes it super easy to build something like this quickly and effectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://x.com/sachittechB/status/1794394988840960149" rel="noopener noreferrer"&gt;Getting raw markdown response from the api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/sachittechB/status/1794395227501019559" rel="noopener noreferrer"&gt;Adding markdown parsing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned for more. Until then, stay safe.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nextjs</category>
      <category>openai</category>
      <category>llm</category>
    </item>
    <item>
      <title>Streamlining Your Code with JavaScript's Reduce Method</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Sat, 17 Jun 2023 15:22:03 +0000</pubDate>
      <link>https://dev.to/sachitsac/streamlining-your-code-with-javascripts-reduce-method-e61</link>
      <guid>https://dev.to/sachitsac/streamlining-your-code-with-javascripts-reduce-method-e61</guid>
      <description>&lt;p&gt;Whether you're just starting out with TypeScript/JavaScript or you're already comfortable with the basics, understanding array methods can significantly enhance your coding efficiency. In this short article, we'll introduce an array method that's often overlooked but incredibly powerful: reduce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Basics
&lt;/h2&gt;

&lt;p&gt;Typically, to manipulate array data, we'd use methods like filter and map. For example, consider an array of students, where each student has a &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;score&lt;/code&gt;, and &lt;code&gt;class&lt;/code&gt;. Say we want to find the average score of all students in &lt;code&gt;Class A&lt;/code&gt; who have scored above 50. A traditional approach using filter and map might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define student interface
interface Student {
    name: string;
    score: number;
    class: string;
}

// Array of students
const students: Student[] = [
    { name: 'John', score: 80, class: 'Class A' },
    { name: 'Jane', score: 40, class: 'Class A' },
    { name: 'Doe', score: 70, class: 'Class B' },
    { name: 'Smith', score: 60, class: 'Class A' },
];

// Filter the students based on class and score
const filteredStudents = students.filter(student =&amp;gt; student.class === 'Class A' &amp;amp;&amp;amp; student.score &amp;gt; 50);

// Get the total score
const total = filteredStudents.map(student =&amp;gt; student.score).reduce((acc, score) =&amp;gt; acc + score, 0);

// Calculate average
const average = total / filteredStudents.length;

console.log(average);

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

&lt;/div&gt;



&lt;p&gt;This code does the job, but it loops over the array three times. Could we make this more efficient?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter &lt;code&gt;reduce&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The reduce method can perform the job of both filter and map in just a single pass. It might seem complex at first, but the power it brings to your code is worth the effort.&lt;/p&gt;

&lt;p&gt;Here's how you might solve the above problem using reduce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define student interface
interface Student {
    name: string;
    score: number;
    class: string;
}

// Define an interface for the data we'll track
interface StudentScoreData {
    totalScore: number;
    studentCount: number;
}

const students: Student[] = [
    { name: 'John', score: 80, class: 'Class A' },
    { name: 'Jane', score: 40, class: 'Class A' },
    { name: 'Doe', score: 70, class: 'Class B' },
    { name: 'Smith', score: 60, class: 'Class A' },
];

// Initialize our tracking data
const initialData: StudentScoreData = { totalScore: 0, studentCount: 0 };

// Use reduce to calculate the total score and student count
const studentScoreData = students.reduce((data, student) =&amp;gt; {
    if (student.class === 'Class A' &amp;amp;&amp;amp; student.score &amp;gt; 50) {
        return { 
            totalScore: data.totalScore + student.score, 
            studentCount: data.studentCount + 1 
        };
    }
    return data;
}, initialData);

// Calculate average
const averageReduce = studentScoreData.totalScore / studentScoreData.studentCount;

console.log(averageReduce);

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

&lt;/div&gt;



&lt;p&gt;In this example, we only loop through the array once, increasing efficiency, particularly when dealing with large arrays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Embracing reduce over filter and map might seem daunting at first, but it's a step worth taking. Not only does it make your code more efficient by reducing the number of iterations, but it also challenges you to think about problems in a slightly different way. &lt;/p&gt;

&lt;p&gt;This article was inspired by this video i saw recently:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/YhLOtIQUrb4?start=1"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>My Struggles with TDD ( Test driven development )</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Sun, 07 May 2023 13:28:50 +0000</pubDate>
      <link>https://dev.to/sachitsac/my-struggles-with-tdd-test-driven-development--32mm</link>
      <guid>https://dev.to/sachitsac/my-struggles-with-tdd-test-driven-development--32mm</guid>
      <description>&lt;p&gt;With nearly 15 years of experience in software development under my belt, one area I've consistently found challenging is Test-Driven Development (TDD). It's not that I don't appreciate the importance of writing tests, nor do I neglect to write them; it's just that I don't adhere to the TDD methodology. To better understand my perspective, let's first explore the what is TDD:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Test-Driven Development (TDD) is a software development approach focused on writing tests before writing code. Developers create tests for expected functionality, write minimal code to pass those tests, and then refactor for optimisation. This iterative process promotes code reliability, maintainability, and easier debugging.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another way to look at TDD:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Loop(Red-&amp;gt;Green-&amp;gt;Refactor) - until equilibrium&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Despite its apparent simplicity in theory, I've grappled with TDD throughout my professional journey. Driven by a desire to uncover the underlying reasons for this struggle and improve my practices, I am determined to embrace the TDD methodology more effectively, ultimately resulting in the production of robust and reliable code.&lt;/p&gt;

&lt;p&gt;Here is what i’ve uncovered so far:&lt;/p&gt;

&lt;h1&gt;
  
  
  1: Personality
&lt;/h1&gt;

&lt;p&gt;Upon delving deeper into my personality traits, particularly optimism and pessimism, I discovered the following:&lt;/p&gt;

&lt;p&gt;I generally lean towards the optimistic side. But how does this optimism influence my tendency to write code first and test later? It's possible that my optimistic nature leads me to believe that my code will function as intended, causing me to prioritise writing code over testing.&lt;/p&gt;

&lt;h1&gt;
  
  
  2: Mindset
&lt;/h1&gt;

&lt;p&gt;As an inherently optimistic individual, I possess a success-oriented mindset accompanied by an innate aversion to failure. This fear has held me back from pursuing numerous opportunities in life. But how does this relate to my reluctance to adopt TDD? It's plausible that my fear of failure deters me from writing tests first; instead, I gravitate towards writing code initially. Once confident in my code's functionality, I then create tests, reinforcing my optimism and success-driven mentality.&lt;/p&gt;

&lt;h1&gt;
  
  
  3: Processes
&lt;/h1&gt;

&lt;p&gt;In a team or company setting, adhering to established processes is crucial. While TDD may initially appear time-consuming, its long-term benefits are undeniable. However, some teams fail to recognise the advantages of TDD, opting instead to prioritise a high output of code and features, inadvertently sacrificing quality for speed. This shortsighted approach can lead to an accumulation of technical debt. My reluctance to follow TDD may be influenced by working in environments where teams disregard the methodology, focusing on short-term productivity while neglecting the long-term stability and maintainability of the codebase.&lt;/p&gt;

&lt;h1&gt;
  
  
  4: Rewards and Recognition
&lt;/h1&gt;

&lt;p&gt;Closely connected to the previous point, there is often a tendency to celebrate teams that rapidly deliver features and code, while inadvertently overlooking those who prioritise quality (a byproduct of TDD). Driven by the desire for rewards and recognition, I may find myself inclined to sidestep TDD methodologies in favour of accelerated output. This behaviour not only impacts my adherence to TDD but also perpetuates a culture that undervalues the long-term benefits of quality-focused development practices.&lt;/p&gt;

&lt;p&gt;In conclusion, my journey to understand the factors contributing to my reluctance in adopting TDD has led me to identify four key areas: personality, mindset, processes, and rewards and recognition. These aspects have shaped my approach to software development, resulting in a tendency to prioritise code creation over testing. Now that I have a some understanding of the underlying reasons, I am better equipped to make conscious efforts towards embracing TDD in my development practices. In my next post, I will outline the strategies and steps I am taking to mitigate these influences and fully integrate TDD into my workflow, ultimately producing more robust and reliable software.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Unleash the power of Partial &lt;T&gt; for mock data perfection!</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Sat, 15 Apr 2023 04:59:46 +0000</pubDate>
      <link>https://dev.to/sachitsac/unleash-the-power-of-partial-for-mock-data-perfection-5akm</link>
      <guid>https://dev.to/sachitsac/unleash-the-power-of-partial-for-mock-data-perfection-5akm</guid>
      <description>&lt;p&gt;TypeScript Partial is a utility type that allows you to create a new type based on an existing one, making all of its properties optional. It is particularly useful when working with partial updates or constructing objects incrementally. In the context of testing, Partial can be a valuable tool for creating mock data. &lt;/p&gt;

&lt;p&gt;Lets take an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface User {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets define a function that creates a mock user for testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createMockUser(userPartial: Partial&amp;lt;User&amp;gt;): User {
  const defaultUser: User = {
    id: 1,
    firstName: 'John',
    lastName: 'Doe',
    email: 'john.doe@example.com',
  };

  return { ...defaultUser, ...userPartial };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;createMockUser&lt;/code&gt; accepts a &lt;code&gt;Partial&amp;lt;User&amp;gt;&lt;/code&gt; object and merges it with a &lt;code&gt;defaultUser&lt;/code&gt; object. This way, you only need to provide the properties relevant to your test, and the function will take care of the rest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mockUser1 = createMockUser({ firstName: 'Jane', lastName: 'Smith' });

const mockUser2 = createMockUser({ email: 'jane.doe@example.com' });

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

&lt;/div&gt;



&lt;p&gt;So what are the advantages of this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Focussed testing&lt;/strong&gt;: You can concentrate on testing specific properties or functionality rather than being overwhelmed by a complex object structure ( which is probably a code smell but a topic for another post ). This helps you write more targeted, efficient tests and makes it easier to identify the purpose of each test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased maintainability&lt;/strong&gt;: Because you no longer need to specify all properties for your mock data, you minimise the need to update your tests when your interfaces change. This makes your tests more maintainable and less prone to breaking due to changes in the underlying data structures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less boilerplate&lt;/strong&gt;: With Partial, you only need to define the properties relevant to your test case, reducing the amount of boilerplate code and making your tests more focused and easier to understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusable mock data creation&lt;/strong&gt;: You can use functions like this that leverage Partial to create mock data easily and consistently across your tests. This promotes reusability and can help you maintain a consistent approach to creating mock data in your test suite. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced readability&lt;/strong&gt;: When using Partial, it becomes clearer which properties of the mocked object are relevant to the test case. This improves the readability of your tests, making it easier for you and your team members to understand and maintain the test suite.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So in summary, Partials can be your best friend when it comes to testing, helping you write clean, consistent, maintainable tests that are more focussed. &lt;/p&gt;

&lt;p&gt;There's one more approach that I have recently come across by none other than our &lt;a href="https://twitter.com/mattpocockuk" rel="noopener noreferrer"&gt;Typescript Wizard: Matt Pocock&lt;/a&gt;. He's created a library called &lt;a href="https://github.com/total-typescript/shoehorn" rel="noopener noreferrer"&gt;shoehorn&lt;/a&gt; that has some utility types. Head over to his article and read more about it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.totaltypescript.com/testing-with-typescript-is-painful-heres-a-solution" rel="noopener noreferrer"&gt;Here's a link to his article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Typescripting :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>testing</category>
    </item>
    <item>
      <title>Typescript: Zod - Handle external api errors gracefully</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Wed, 11 Jan 2023 12:08:09 +0000</pubDate>
      <link>https://dev.to/sachitsac/zod-handle-external-api-errors-gracefully-4k3c</link>
      <guid>https://dev.to/sachitsac/zod-handle-external-api-errors-gracefully-4k3c</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/sachitsac/typescript-type-guards-with-zod-1m12"&gt;In our previous post&lt;/a&gt;, we discussed a very cool library called &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; and how we can use it to write user defined type guards. In this post, lets look at another use case / issue this library helps resolve easily.&lt;/p&gt;

&lt;p&gt;Lets look at the problem first. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You have an app that consumes data from external api's for example google maps or weather api.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You are working in a micro services environment and  consume api's from other teams services that are loosely bound with contracts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You apps have background processes ( async event handlers ) that require particular data to be passed in for it to process the event.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets look at this problem in code: We want to get weather for a given user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface User {
  id: number;
  name: string;
  address?: string;
}

interface Weather {
  summary: string;
  max: number;
  min: number;
  chanceOfRain: number;
}

interface UserWeatherResponse {
  user: User;
  weather: Weather;
}

interface ResponseFromGoogleApi {
  summary: string;
  max: number;
  min: number;
  chanceOfRain: number;
  humidity: number;
}

function getUserService() {
  return {
    getUserById: (id: User["id"]) =&amp;gt; ({
      id,
      name: "John Doe",
      email: "john@doe.com",
    }),
  };
}

function getWeatherFromGoogleApi(address: string): Weather {
  const responseFromGoogle: ResponseFromGoogleApi = {
    summary: "It will be a nice sunny day",
    max: 20,
    min: 20,
    chanceOfRain: 0,
    humidity: 10,
  };

  return {
    summary: responseFromGoogle.summary,
    max: responseFromGoogle.max,
    min: responseFromGoogle.min,
    chanceOfRain: responseFromGoogle.chanceOfRain,
  };
}

function getWeatherService() {
  return {
    getWeatherForUser: (user: User) =&amp;gt;
      getWeatherFromGoogleApi(user.address ?? ""),
  };
}

const userService = getUserService();
const weatherService = getWeatherService();

export const getUserWeather = (
  params: { id: number },
): UserWeatherResponse =&amp;gt; {
  const user = userService.getUserById(params.id);
  const weather = weatherService.getWeatherForUser(user);

  return {
    user,
    weather,
  };
};


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

&lt;/div&gt;



&lt;p&gt;So basically, the code above is simulating getting weather for a user from google api, that is an external dependency that our application needs in order to resolve weather requests from our users.&lt;/p&gt;

&lt;p&gt;So what are the potential pitfalls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google api is an external dependency that we have no control over.&lt;/li&gt;
&lt;li&gt;Google can choose to change its api response payload at any time.&lt;/li&gt;
&lt;li&gt;Response from google api is an unknown in our application.&lt;/li&gt;
&lt;li&gt;We have made assumptions as to what the response from google api will look like.&lt;/li&gt;
&lt;li&gt;Google api's can have downtime and affect runtime of our application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So while our application is typesafe at compile time, it is not immune to run time errors. For example, if goolge api does not return the required data, our application will still compile, but will break when the user is trying to access it from the browser ( runtime failure ). &lt;/p&gt;

&lt;p&gt;Now this is where Zod excels. It can safely parse data from external api's and add runtime type safety to our application and we can gracefully handle those issue without affection the user experience. Lets take a look at how this can be done using zod:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define our schema ( interfaces ) using zod.&lt;/li&gt;
&lt;li&gt;We derive the type from the schema we defined.&lt;/li&gt;
&lt;li&gt;We use zod to ensure the shape of the data we get from the external api is the same as what we expect in our application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import z from "zod";

interface User {
  id: number;
  name: string;
  address?: string;
}

const weatherSchema = z.object({
  summary: z.string(),
  max: z.number(),
  min: z.number(),
  chanceOfRain: z.number(),
});

type Weather = z.infer&amp;lt;typeof weatherSchema&amp;gt;;

interface UserWeatherResponse {
  user: User;
  weather: Weather;
}

interface UserWeatherResponseError {
  message: string;
}

const responseFromGoogleApiSchema = z.object({
  summary: z.string(),
  max: z.number(),
  min: z.number(),
  chanceOfRain: z.number(),
  humidity: z.number(),
});

type ResponseFromGoogleApi = z.infer&amp;lt;typeof responseFromGoogleApiSchema&amp;gt;

function getUserService() {
  return {
    getUserById: (id: User["id"]) =&amp;gt; ({
      id,
      name: "John Doe",
      email: "john@doe.com",
    }),
  };
}

function getWeatherFromGoogleApi(address: string): Weather | Error {
  const responseFromGoogle: ResponseFromGoogleApi = {
    summary: "It will be a nice sunny day",
    max: 20,
    min: 20,
    chanceOfRain: 0,
    humidity: 10,
  };

  if (!responseFromGoogleApiSchema.safeParse(responseFromGoogle).success) {
    // gracefull handler error here and return appropriate response to the user
    return new Error("Response from google is not what we expected, lets bail out here quickly")
  }

  return {
    summary: responseFromGoogle.summary,
    max: responseFromGoogle.max,
    min: responseFromGoogle.min,
    chanceOfRain: responseFromGoogle.chanceOfRain,
  };
}

function getWeatherService() {
  return {
    getWeatherForUser: (user: User) =&amp;gt;
      getWeatherFromGoogleApi(user.address ?? ""),
  };
}

const userService = getUserService();
const weatherService = getWeatherService();

export const getUserWeather = (
  params: { id: number },
): UserWeatherResponse | UserWeatherResponseError =&amp;gt; {
  const user = userService.getUserById(params.id);
  const weather = weatherService.getWeatherForUser(user);

  if (!weatherSchema.safeParse(weather).success) {
    return {
      message: "Cannot find weather for the user"
    }
  }

  return {
    user,
    weather,
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In summary, zod helps us easily add runtime type safety to our application. It allows us to ensure what we expect is what we get and if we don't, we can gracefully handle those errors ( no matter the reason ) and improve our application uptime and user experience.&lt;/p&gt;

&lt;p&gt;2023, the year of Zod.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>career</category>
      <category>firstpost</category>
    </item>
    <item>
      <title>Typescript: Type guards with zod</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Wed, 21 Dec 2022 12:26:28 +0000</pubDate>
      <link>https://dev.to/sachitsac/typescript-type-guards-with-zod-1m12</link>
      <guid>https://dev.to/sachitsac/typescript-type-guards-with-zod-1m12</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/sachitsac/typescript-type-guards-9m1"&gt;In our previous post&lt;/a&gt;, we discussed how we can use User defined type guards and their advantages. &lt;/p&gt;

&lt;p&gt;In this post, i'd like to show the same concept but with a popular typescript library called &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt;. Zod is a very powerful library that gives runtime safety to applications written in typescript.&lt;/p&gt;

&lt;p&gt;Lets start by looking at an example of user guard written in plain typescript.&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%2Fwyinth8dqq4xyfx7pca0.png" 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%2Fwyinth8dqq4xyfx7pca0.png" alt=" " width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So lets break it down as to what is happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have a user interface with 3 string properties and 1 boolean.&lt;/li&gt;
&lt;li&gt;We have a type guard that validates if an object passed is a typeof User.&lt;/li&gt;
&lt;li&gt;The type guard is checking each mandatory fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So i can already think of few issues with the type guard.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We could just validate a property against its primitive type, e.g. &lt;code&gt;typeof obj.email === 'string'&lt;/code&gt; and we can pass any value.&lt;/li&gt;
&lt;li&gt;We can pass any valid string to the uuid but is it really a uuid ?&lt;/li&gt;
&lt;li&gt;Same can be said about the email, we can pass any valid string and it'll satisfy the guard.&lt;/li&gt;
&lt;li&gt;We could also add mandatory properties to the user interface later and completely forget to add them to the type guard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now lets rewrite the above but this time using &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt;&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%2Fpdnlnm8avo2poux4i8vl.png" 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%2Fpdnlnm8avo2poux4i8vl.png" alt=" " width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; allows you to write your schemas for objects and its validations in the same place. e.g. uuid and email are defined as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uuid: z.string().uuid()
email: z.string().email()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only is it much cleaner, less code and more useful, it also future proofs the code as we can add more properties to the schema without needing to update the type guard.&lt;/p&gt;

&lt;p&gt;Please checkout &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; library as to me, it is one of the must have in your codebase if you care about runtime stability and experience of your applications.&lt;/p&gt;

&lt;p&gt;Until next time, happy Zoding!&lt;/p&gt;

&lt;p&gt;PS: You can find the code in the &lt;a href="https://gist.github.com/sachitsac/33caed8e063cfc7fe522c0b4ce9ad5e9" rel="noopener noreferrer"&gt;Gist here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>software</category>
      <category>devops</category>
    </item>
    <item>
      <title>Typescript: User Defined Type guards</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Sun, 18 Dec 2022 12:56:42 +0000</pubDate>
      <link>https://dev.to/sachitsac/typescript-type-guards-9m1</link>
      <guid>https://dev.to/sachitsac/typescript-type-guards-9m1</guid>
      <description>&lt;p&gt;In our previous post &lt;a href="https://dev.to/sachitsac/typescript-unknown-vs-any-fld"&gt;any vs unknown&lt;/a&gt;, we talked about type narrowing. Basically type narrowing is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The process of refining types to more specific types than declared is called narrowing. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For javascript primitives ( string, number, bigint, boolean, undefined, symbol, null) that can contain values, we can use the special typeof operator to narrow the type. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ensuring age is a number if we don't know the value
// eg. it might be an any or unknown
if ( typeof age === 'number' ) { ... }
// or
if (typeof signature === 'string' { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all good when we have a primitive, but what if we have an object, how do we use the same technique of narrowing. But before that, why would we even need to do that ?&lt;/p&gt;

&lt;p&gt;So here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Pet {
  speak: () =&amp;gt; void;
}

interface Fish extends Pet {
  swim: () =&amp;gt; void;
}

interface Bird extends Pet {
  fly: () =&amp;gt; void;
}

interface Cow extends Pet {
  milk: () =&amp;gt; void;
}

// Essentially, the subject is a union type of Cat or Dog
function flyPet(subject: Fish | Bird | Cow ) {
  subject.fly();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the subject variable passed to the function &lt;code&gt;flyPet&lt;/code&gt;, is a union type of Bird or Fish or Cow. Other than the speech, each pet have their own trait. For example, fish can swim and bird can fly.&lt;/p&gt;

&lt;p&gt;So if we invoke the function &lt;code&gt;flyPet&lt;/code&gt;, then we will get a compile time error:&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%2Fjabxl61vp7db8w3t4aoz.png" 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%2Fjabxl61vp7db8w3t4aoz.png" alt=" " width="800" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this is good when we know the subject type. Now to why we need this, imagine if we didn't know the type of subject, eg. it was &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt; as the data might be coming from an external api or its legacy code that we don't know what the type is genuinely, that would result in a run time error instead of catching it at compile time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function flyPet(subject: any ) {
  // compiler happy, but will result in a runtime error
  subject.fly();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can prevent those runtime errors by using the technique of type narrowing by creating &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates" rel="noopener noreferrer"&gt;user defined type guards&lt;/a&gt;. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function isBird(obj: any): obj is Bird {
  if (!obj.hasOwnProperty('fly') || !(typeof obj.fly === 'function')) {
    return false;
  }
  return true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Function breakdown: We assert that for an object to be a bird&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It needs to have a property &lt;code&gt;fly&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;And the property &lt;code&gt;fly&lt;/code&gt; is an executable function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can rewrite our &lt;code&gt;flyPet&lt;/code&gt; function to be run time safe like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function flyPet(subject: any ): void {
  if (isBird(subject)) {
    subject.fly();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we use our type guard, we have basically narrowed down the type to be a bird and anything inside the if scope, will be a bird and hence we can use our subject to fly.&lt;/p&gt;

&lt;p&gt;In summary, User defined Type guards allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Narrow down the type for objects&lt;/li&gt;
&lt;li&gt;Prevent runtime errors that are not caught compile time.&lt;/li&gt;
&lt;li&gt;Practice safe programming techniques&lt;/li&gt;
&lt;li&gt;Catch errors and not break the user application / experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://dev.to/sachitsac/typescript-type-guards-with-zod-1m12"&gt;In the next post&lt;/a&gt;, we will look at the concept of User defined type guards using a very popular library called &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; and how it can make it easier to write user defined type guards.&lt;/p&gt;

&lt;p&gt;Till then, happy guarding.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Is Chat GPT going to take over our jobs ?</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Wed, 14 Dec 2022 23:47:11 +0000</pubDate>
      <link>https://dev.to/sachitsac/is-chat-gpt-going-to-take-over-our-jobs--10n5</link>
      <guid>https://dev.to/sachitsac/is-chat-gpt-going-to-take-over-our-jobs--10n5</guid>
      <description>&lt;p&gt;Hey Guys,&lt;/p&gt;

&lt;p&gt;Just sharing that the #2: December edition post for My Techy bites newsletter is out. It contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design tokens&lt;/li&gt;
&lt;li&gt;ChatGPT demo and thoughts&lt;/li&gt;
&lt;li&gt;Hooked, the book that shows how to build habit forming products&lt;/li&gt;
&lt;li&gt;Playwright - End to End testing took from Microsoft&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a link to the post&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://sachitm.substack.com/p/3-december-edition" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZOhSh_pA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://substackcdn.com/image/youtube/w_728%2Cc_limit/wtTstdiBuUk" height="410" class="m-0" width="728"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://sachitm.substack.com/p/3-december-edition" rel="noopener noreferrer" class="c-link"&gt;
          #3: December Edition - by Sachit Malhotra - My Tech Bytes
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Design tokens, ChatGPT, Hooked and e2e testing tool
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--kLiQayBt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/72eb4102-e967-4568-a44f-a548ad85927b/favicon.ico" width="64" height="64"&gt;
        sachitm.substack.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Like, share and subscribe to the newsletter if you like it.&lt;/p&gt;

&lt;p&gt;Thanks&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Typescript: unknown vs any</title>
      <dc:creator>Sachit</dc:creator>
      <pubDate>Mon, 12 Dec 2022 06:43:03 +0000</pubDate>
      <link>https://dev.to/sachitsac/typescript-unknown-vs-any-fld</link>
      <guid>https://dev.to/sachitsac/typescript-unknown-vs-any-fld</guid>
      <description>&lt;p&gt;Do you know the difference between &lt;code&gt;unknown&lt;/code&gt; and &lt;code&gt;any&lt;/code&gt; in typescript ? Do you know when is it useful to use &lt;code&gt;unknown&lt;/code&gt; or &lt;code&gt;any&lt;/code&gt; ? Do you know why using any is not recommended ? Well, here's a explanation of the differences and uses.&lt;/p&gt;

&lt;p&gt;The type &lt;code&gt;any&lt;/code&gt; was added to typescript to allow easy migration of the code for any javascript project. &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; are mostly the same with a key difference:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;unknown&lt;/code&gt; does not allow access to any property on an object or variable or use any primitive methods. This is useful when you either don't know the shape of data you are dealing with or are migrating from legacy javascript code. &lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a: any = '123';
a.toFixed(2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing this will result in a runtime error:&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%2Fdyjbzskalv6cdu6jddr1.png" 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%2Fdyjbzskalv6cdu6jddr1.png" alt=" " width="676" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets change the &lt;code&gt;any&lt;/code&gt; to &lt;code&gt;unknown&lt;/code&gt; and see what happens&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a: unknown = '123';
a.toFixed(2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing this with an &lt;code&gt;unknown&lt;/code&gt; type will raise a compiler error. &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%2Fkpm49b2ptvfe7v6cmvoj.png" 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%2Fkpm49b2ptvfe7v6cmvoj.png" alt=" " width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix the above, we have to narrow the type (using truthiness narrowing) to a number using a type guard like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a: unknown = 123;
if (typeof a === 'number') {
  console.log(a.toFixed(2)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In short, benefits of using &lt;code&gt;unknown&lt;/code&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leads us to use type narrowing ( article on this coming soon )&lt;/li&gt;
&lt;li&gt;Refactoring legacy javascript code to typescript&lt;/li&gt;
&lt;li&gt;Catch bugs early in the development cycle&lt;/li&gt;
&lt;li&gt;Preventing runtime bugs in applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See a short video that explains this in details.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wOa67sZyO54"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hope you find this useful.&lt;/p&gt;

&lt;p&gt;We will discuss &lt;code&gt;type narrowing&lt;/code&gt;, &lt;code&gt;type assertion&lt;/code&gt; and &lt;code&gt;type guards&lt;/code&gt; in the next few posts.&lt;/p&gt;

&lt;p&gt;Until them, stay safe, stay healthy.&lt;/p&gt;

</description>
      <category>devto</category>
      <category>community</category>
    </item>
  </channel>
</rss>
