<?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: Abdulmalik Muhammad</title>
    <description>The latest articles on DEV Community by Abdulmalik Muhammad (@abdulmalik_muhammad).</description>
    <link>https://dev.to/abdulmalik_muhammad</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%2F3864663%2F8829f530-c86d-4d9c-821d-13a7724a0a46.jpg</url>
      <title>DEV Community: Abdulmalik Muhammad</title>
      <link>https://dev.to/abdulmalik_muhammad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abdulmalik_muhammad"/>
    <language>en</language>
    <item>
      <title>Advanced TypeScript Patterns Worth Actually Learning (Part 1)</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Sat, 11 Apr 2026 00:59:17 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/advanced-typescript-patterns-worth-actually-learning-part-1-4eob</link>
      <guid>https://dev.to/abdulmalik_muhammad/advanced-typescript-patterns-worth-actually-learning-part-1-4eob</guid>
      <description>&lt;p&gt;There's a point in every TypeScript developer's journey where you stop fighting the compiler and start working with it. These patterns are what got me there.&lt;/p&gt;

&lt;p&gt;They're not just clever tricks. They solve real problems that come up when you're building production software.&lt;/p&gt;




&lt;p&gt;Branded types for primitive safety&lt;/p&gt;

&lt;p&gt;TypeScript treats &lt;code&gt;string&lt;/code&gt; as &lt;code&gt;string&lt;/code&gt;. So if you have a &lt;code&gt;UserId&lt;/code&gt; and an &lt;code&gt;OrderId&lt;/code&gt;, both strings, the compiler won't stop you from mixing them up. Branded types fix that.&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;Brand&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;B&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_brand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Brand&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UserId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OrderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Brand&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OrderId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;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;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserId&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;orderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// error, as it should be&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you start using this in a fintech or any domain-heavy codebase, you'll wonder how you lived without it.&lt;/p&gt;




&lt;p&gt;Mapped types for transforming shapes&lt;/p&gt;

&lt;p&gt;Instead of manually creating variations of a type, let TypeScript do it for you.&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;Nullable&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="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&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;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="k"&gt;readonly&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Optional&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are simple examples but the pattern scales. You can filter keys, remap them, add modifiers conditionally. Very useful when you're deriving API response types from your internal models.&lt;/p&gt;




&lt;p&gt;Conditional types for smart generics&lt;/p&gt;

&lt;p&gt;This is where TypeScript starts feeling like a programming language within a programming language.&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;IsArray&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="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&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;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Flatten&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="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Item&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;Item&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="c1"&gt;// usage&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Flatten&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Flatten&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="c1"&gt;// number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flatten is a real pattern I use when dealing with API responses that sometimes return an array and sometimes return a single item. Handle it at the type level and the rest of the code stays clean.&lt;/p&gt;

&lt;p&gt;That's part one. Part two covers function overloads, template literal types, recursive types, and &lt;code&gt;as const&lt;/code&gt; maps. Coming soon.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Common Mistakes I See in Node.js Backends (And How to Fix Them)</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Sat, 11 Apr 2026 00:52:10 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/common-mistakes-i-see-in-nodejs-backends-and-how-to-fix-them-4peg</link>
      <guid>https://dev.to/abdulmalik_muhammad/common-mistakes-i-see-in-nodejs-backends-and-how-to-fix-them-4peg</guid>
      <description>&lt;p&gt;I've worked on enough Node.js backends at this point to start seeing the same problems come up over and over. Some of them are beginner mistakes. Some of them show up in codebases written by people who really should know better.&lt;/p&gt;

&lt;p&gt;Here are the ones I see most often.&lt;/p&gt;




&lt;p&gt;Not handling async errors properly&lt;/p&gt;

&lt;p&gt;This one is everywhere. Someone writes an async function, forgets to wrap it in a try/catch, and now unhandled promise rejections are silently swallowing errors in production.&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="c1"&gt;// this will swallow errors&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// this won't&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;p&gt;Better yet, use a wrapper utility or a library like &lt;code&gt;express-async-errors&lt;/code&gt; so you don't have to repeat that pattern everywhere.&lt;/p&gt;




&lt;p&gt;Putting everything in one file&lt;/p&gt;

&lt;p&gt;I've opened Node.js projects where the entire app, routes, business logic, database calls, and middleware, lives in a single &lt;code&gt;index.js&lt;/code&gt;. It works until it doesn't. Once the project grows it becomes impossible to navigate and a nightmare to test.&lt;/p&gt;

&lt;p&gt;A simple structure goes a long way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  routes/
  controllers/
  services/
  middleware/
  utils/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controllers handle the request and response. Services handle the business logic. Keep them separate and your codebase stays readable as it scales.&lt;/p&gt;




&lt;p&gt;Blocking the event loop&lt;/p&gt;

&lt;p&gt;Node.js is single threaded. If you run a heavy synchronous operation on the main thread, everything else waits. I've seen people do things like parse a large JSON file synchronously or run a CPU intensive calculation right in a route handler.&lt;/p&gt;

&lt;p&gt;If you have heavy work to do, offload it. Use worker threads, a job queue, or move it out of the request cycle entirely.&lt;/p&gt;




&lt;p&gt;No validation on incoming data&lt;/p&gt;

&lt;p&gt;Trusting whatever comes in from the client is asking for trouble. I've seen backends that pass &lt;code&gt;req.body&lt;/code&gt; directly into a database query with zero validation. That's how you get corrupted data and security issues.&lt;/p&gt;

&lt;p&gt;Use a validation library like &lt;code&gt;zod&lt;/code&gt; or &lt;code&gt;joi&lt;/code&gt;. Define your schema, validate early, and reject bad input before it gets anywhere near your business logic.&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;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&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="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;positive&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;No centralized error handling&lt;/p&gt;

&lt;p&gt;Error handling scattered across every route is messy and inconsistent. Users end up getting different error shapes depending on which route blew up. Set up a single error handling middleware and funnel everything through 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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One place to update, consistent responses everywhere.&lt;/p&gt;




&lt;p&gt;Ignoring environment configuration&lt;/p&gt;

&lt;p&gt;Hardcoded secrets, API keys sitting in the codebase, no &lt;code&gt;.env&lt;/code&gt; setup. Still happens more than it should. Use &lt;code&gt;dotenv&lt;/code&gt;, never commit secrets, and validate your environment variables at startup so the app fails loudly if something is missing rather than breaking mysteriously at runtime.&lt;/p&gt;




&lt;p&gt;No logging worth reading&lt;/p&gt;

&lt;p&gt;&lt;code&gt;console.log("error:", err)&lt;/code&gt; is not a logging strategy. In production you need structured logs you can actually search and filter. Something like &lt;code&gt;winston&lt;/code&gt; or &lt;code&gt;pino&lt;/code&gt; gives you log levels, JSON output, and the ability to plug into whatever monitoring setup you're using.&lt;/p&gt;

&lt;p&gt;If you can't tell what your backend was doing when something went wrong, that's a problem you'll feel at the worst possible time.&lt;/p&gt;




&lt;p&gt;None of these are hard to fix. Most of them just require slowing down and being intentional about how the project is set up from the start. A backend that's easy to debug and maintain is worth more than one that was fast to throw together.&lt;/p&gt;

</description>
      <category>node</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>backend</category>
    </item>
    <item>
      <title>Things I Wish I Knew Before Building My First React Native App</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Thu, 09 Apr 2026 22:45:15 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/things-i-wish-i-knew-before-building-my-first-react-native-app-40a5</link>
      <guid>https://dev.to/abdulmalik_muhammad/things-i-wish-i-knew-before-building-my-first-react-native-app-40a5</guid>
      <description>&lt;p&gt;I remember the first time I opened a React Native project. I thought, I already know React, how different can this be?&lt;/p&gt;

&lt;p&gt;Pretty different, it turns out.&lt;/p&gt;

&lt;p&gt;Here's what I wish someone had told me before I wasted time figuring it out myself.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;The bridge is not free&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Early on I treated React Native like a browser. I passed big objects around, called native modules constantly, didn't think twice about it. Then I started noticing janky animations and sluggish interactions.&lt;/p&gt;

&lt;p&gt;The JavaScript thread and the native thread are separate. Every time they talk to each other there's a cost. The more you understand that, the better decisions you make about where logic lives and how often you cross that bridge.&lt;/p&gt;




&lt;p&gt;StyleSheet.create is not just for organization&lt;/p&gt;

&lt;p&gt;I was using inline styles everywhere when I started because it felt easier. Turns out &lt;strong&gt;StyleSheet.create&lt;/strong&gt; isn't just a pattern for keeping things tidy. It validates styles at compile time and optimizes them so they don't get recreated on every render.&lt;/p&gt;

&lt;p&gt;Small thing but it adds up across a whole app.&lt;/p&gt;




&lt;p&gt;FlatList will bite you if you ignore it&lt;/p&gt;

&lt;p&gt;I made the mistake of rendering long lists with a plain &lt;strong&gt;ScrollView&lt;/strong&gt; early on. It works, until it doesn't. &lt;strong&gt;FlatList&lt;/strong&gt; exists for a reason. It only renders what's on screen. Once your list grows past a certain point, the difference is night and day.&lt;/p&gt;

&lt;p&gt;Also, always set &lt;strong&gt;keyExtractor&lt;/strong&gt;. Don't let React Native guess.&lt;/p&gt;




&lt;p&gt;Navigation state is its own beast&lt;/p&gt;

&lt;p&gt;Coming from web, I assumed routing would feel familiar. It doesn't, not really. React Navigation has its own mental model and the stack, tab, and drawer navigators each behave differently. I spent way too long fighting navigation bugs that were actually me misunderstanding how the navigator was managing state.&lt;/p&gt;

&lt;p&gt;Read the docs properly before you build. It saves you a lot of pain later.&lt;/p&gt;




&lt;p&gt;Test on a real device early&lt;/p&gt;

&lt;p&gt;The simulator is convenient but it lies to you. Performance feels fine in the simulator and then you run it on a mid-range Android and everything falls apart. I learned to keep a physical device nearby from day one.&lt;/p&gt;

&lt;p&gt;Also, Android and iOS behave differently more often than you'd expect. Don't assume something works on both just because it works on one.&lt;/p&gt;




&lt;p&gt;Expo is not cheating&lt;/p&gt;

&lt;p&gt;There was a phase where I thought using Expo meant I wasn't doing it properly. That's nonsense. Expo managed workflow is legitimate and handles a lot of the setup and tooling pain so you can focus on actually building. When you need bare metal access you can eject. But start simple until you have a reason not to.&lt;/p&gt;




&lt;p&gt;The ecosystem moves fast&lt;/p&gt;

&lt;p&gt;Libraries you depend on today might be unmaintained in a year. React Native itself ships breaking changes. I learned to be intentional about what I pull in and to keep an eye on the health of dependencies before committing to them in a production app.&lt;/p&gt;




&lt;p&gt;React Native is genuinely great once you understand how it works under the hood. Most of the frustration early on comes from treating it like the web when it isn't. The sooner you accept that, the faster things click.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>mobile</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What Building Fintech Apps Taught Me About Writing Better Code</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Wed, 08 Apr 2026 23:34:26 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/what-building-fintech-apps-taught-me-about-writing-better-code-3bmc</link>
      <guid>https://dev.to/abdulmalik_muhammad/what-building-fintech-apps-taught-me-about-writing-better-code-3bmc</guid>
      <description>&lt;p&gt;Fintech is unforgiving. You're dealing with real money and real users. A glitch in a social app is a bad UX moment. A glitch in a payment flow means someone loses money or trust, sometimes both.&lt;/p&gt;

&lt;p&gt;After spending years building across fintech and crypto products, here's what that environment actually drilled into me.&lt;/p&gt;




&lt;p&gt;You start thinking about failure first&lt;/p&gt;

&lt;p&gt;In most apps you can afford to be a little optimistic. In fintech you can't. What happens if the network drops mid-transaction? What if the user hits the button twice? What if the third party API returns a 200 with a broken body?&lt;/p&gt;

&lt;p&gt;You stop treating edge cases as afterthoughts. That habit sticks with you even when you move to lower stakes projects.&lt;/p&gt;




&lt;p&gt;Types stop being optional&lt;/p&gt;

&lt;p&gt;When you're moving money around, a &lt;strong&gt;string&lt;/strong&gt; where a &lt;strong&gt;number&lt;/strong&gt; should be is not something you push to fix later. I became a much more deliberate TypeScript user building fintech than I ever was before. Strict mode on, no shortcuts, model your data properly from day one.&lt;/p&gt;

&lt;p&gt;The compiler catching something before production feels different when what it caught could have caused a financial discrepancy.&lt;/p&gt;




&lt;p&gt;Idempotency becomes second nature&lt;/p&gt;

&lt;p&gt;This one trips up a lot of developers who haven't built payment systems. If a user submits a payment and the response never comes back, what happens when they retry? Does it charge twice?&lt;/p&gt;

&lt;p&gt;Designing endpoints so the same request always produces the same result no matter how many times it's called is something you bake in from the start in fintech. Once you think that way, you start applying it everywhere.&lt;/p&gt;




&lt;p&gt;Logging stops being an afterthought&lt;/p&gt;

&lt;p&gt;In a regular app, a bug report comes in and you dig through the code. In fintech, you need to reconstruct exactly what happened, in what order, with what data, at what time. Structured logging and audit trails stop feeling like nice-to-haves really fast.&lt;/p&gt;

&lt;p&gt;If you can't explain what your system did, that's a problem.&lt;/p&gt;




&lt;p&gt;User trust is the actual product&lt;/p&gt;

&lt;p&gt;The feature set matters. Performance matters. But the thing fintech taught me most is that users are trusting you with something real. The moment that trust breaks, it's very hard to get back.&lt;/p&gt;

&lt;p&gt;That changes how you approach everything, from how errors show up in the UI to how you write copy for a failed transaction screen.&lt;/p&gt;




&lt;p&gt;I've worked across a few domains now and fintech sharpened me more than any of them. Not because the code was harder, but because the cost of carelessness was real.&lt;/p&gt;

&lt;p&gt;If you get a chance to build in a high stakes environment, take it. You'll write better software everywhere else because of it.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>career</category>
    </item>
    <item>
      <title>TypeScript Tricks I Actually Use Day to Day</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Tue, 07 Apr 2026 23:42:05 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/typescript-tricks-i-actually-use-day-to-day-3a1l</link>
      <guid>https://dev.to/abdulmalik_muhammad/typescript-tricks-i-actually-use-day-to-day-3a1l</guid>
      <description>&lt;p&gt;I've been writing TypeScript for a few years now across React Native, Node.js, and a bunch of different product types. And there's a gap between what the docs teach you and what you actually end up reaching for every day.&lt;br&gt;
Here are the patterns I keep coming back to.&lt;/p&gt;

&lt;p&gt;Discriminated unions for state management&lt;br&gt;
This one changed how I model data. Instead of a bunch of optional fields that may or may not exist, you define each state explicitly.&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;RequestState&lt;/span&gt; &lt;span class="o"&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;data&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="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;message&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now TypeScript knows exactly what's available in each case. No more &lt;strong&gt;data might be undefined checks&lt;/strong&gt; scattered everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;satisfies&lt;/strong&gt; instead of direct type annotation&lt;/p&gt;

&lt;p&gt;This one's newer but I use it a lot now. The difference is subtle but useful.&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;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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="nx"&gt;satisfies&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="kr"&gt;string&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="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;strong&gt;satisfies&lt;/strong&gt;, you get type checking without losing the literal types. If you annotate directly with &lt;strong&gt;Record&lt;/strong&gt;, you lose the specific values. Small thing, big difference when you're chaining or inferring from it.&lt;/p&gt;




&lt;p&gt;Utility types you actually need&lt;/p&gt;

&lt;p&gt;Everyone knows &lt;strong&gt;Partial&lt;/strong&gt; and &lt;strong&gt;Required&lt;/strong&gt;. These are the ones I reach for more often:&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="c1"&gt;// Pick only what you need&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Preview&lt;/span&gt; &lt;span class="o"&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;Article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&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;slug&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;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Exclude what you don't&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PublicUser&lt;/span&gt; &lt;span class="o"&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="s2"&gt;password&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;token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Make specific fields optional&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UpdateInput&lt;/span&gt; &lt;span class="o"&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="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;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last one is something I use constantly for update/patch endpoints.&lt;/p&gt;




&lt;p&gt;Template literal types for string contracts&lt;br&gt;
Useful when you're dealing with event names, routes, or anything string-based that needs 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;HttpMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&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;POST&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;PUT&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;DELETE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;HttpMethod&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;span class="nx"&gt;Endpoint&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET /users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// valid&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH /users&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&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Catches a whole class of bugs at compile time instead of runtime.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;infer&lt;/strong&gt; for extracting types from generics&lt;/p&gt;

&lt;p&gt;Looks scary at first but once it clicks, you use it everywhere.&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="nb"&gt;ReturnType&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="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &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="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UnpackPromise&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="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;U&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;U&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use &lt;strong&gt;UnpackPromise&lt;/strong&gt; constantly when working with async functions and I need the resolved type without awaiting.&lt;/p&gt;




&lt;p&gt;Const assertions for config objects&lt;/p&gt;

&lt;p&gt;Stop widening your types when you don't need to.&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;const&lt;/span&gt; &lt;span class="nx"&gt;ROLES&lt;/span&gt; &lt;span class="o"&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;admin&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;user&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;guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ROLES&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="c1"&gt;// "admin" | "user" | "guest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, no manual duplication, and the type stays in sync automatically.&lt;/p&gt;

&lt;p&gt;None of these are exotic. They're just the things that come up over and over when you're building real products. The more you use them the more the TypeScript compiler starts feeling like a teammate rather than something you're fighting against.&lt;/p&gt;

&lt;p&gt;That's the shift worth chasing.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>reactnative</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Stay Sharp as a Senior Dev (Without Burning Out)</title>
      <dc:creator>Abdulmalik Muhammad</dc:creator>
      <pubDate>Mon, 06 Apr 2026 23:28:37 +0000</pubDate>
      <link>https://dev.to/abdulmalik_muhammad/how-i-stay-sharp-as-a-senior-dev-without-burning-out-2jgo</link>
      <guid>https://dev.to/abdulmalik_muhammad/how-i-stay-sharp-as-a-senior-dev-without-burning-out-2jgo</guid>
      <description>&lt;p&gt;Five years in and honestly, the thing I didn't expect to fight against is comfort.&lt;/p&gt;

&lt;p&gt;You get to a point where things just... work. You know the patterns. You've seen the bugs. You can set up a project without thinking. That's great until you realize you haven't actually been challenged in months.&lt;/p&gt;

&lt;p&gt;Here's what's been working for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build something you don't understand yet&lt;/strong&gt;&lt;br&gt;
Not at work. On the side. Pick something that's slightly outside your zone and just start poking at it. I've been messing around with VoIP and SIP stuff lately, nowhere near my usual React Native and Node.js world. It's uncomfortable. That's kind of the whole point.&lt;/p&gt;

&lt;p&gt;You don't have to finish it. Just stay curious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read more code than you write&lt;/strong&gt;&lt;br&gt;
Not tutorials. Actual source code of libraries you use every day. Open it up and read it like a book. You'll find things that surprise you, and occasionally things that make you go "wait, why did they do it like that?" Both are useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explain things regularly&lt;/strong&gt;&lt;br&gt;
Write a post. Walk a junior through something. Do a quick internal talk. It doesn't matter. The moment you try to explain something clearly, you find out fast where your understanding actually has holes. Happens to me every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship the ugly version first&lt;/strong&gt;&lt;br&gt;
This one took me a while. Senior devs tend to want to get it right from the start. But sometimes the right move is to ship something rough, see how it actually gets used, then fix it. Real usage teaches you things no amount of upfront thinking will.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Switch contexts when you can&lt;/strong&gt;&lt;br&gt;
New domain, new stack, new team, whatever you can manage. Every time I've moved into a new space (fintech, crypto, AI products) I've hit problems I wasn't ready for. That friction is where most of my actual growth has happened.&lt;/p&gt;

&lt;p&gt;Staying sharp isn't really about doing more. It's about not going numb. The best senior devs I know aren't the ones working the hardest, they're the ones who are still genuinely interested after years of doing this.&lt;/p&gt;

&lt;p&gt;That's what I'm chasing anyway.&lt;/p&gt;

</description>
      <category>career</category>
      <category>typescript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
