<?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>Forem: Pedro Figueiredo</title>
    <description>The latest articles on Forem by Pedro Figueiredo (@pffigueiredo).</description>
    <link>https://forem.com/pffigueiredo</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%2F162462%2F1dcd4d0f-b60c-454f-8a68-c5e7b8f8e753.jpg</url>
      <title>Forem: Pedro Figueiredo</title>
      <link>https://forem.com/pffigueiredo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pffigueiredo"/>
    <language>en</language>
    <item>
      <title>Interact with Neon APIs using Claude Code through natural language</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Fri, 29 Aug 2025 15:20:38 +0000</pubDate>
      <link>https://forem.com/neon-postgres/interact-with-neon-apis-using-claude-code-through-natural-language-267e</link>
      <guid>https://forem.com/neon-postgres/interact-with-neon-apis-using-claude-code-through-natural-language-267e</guid>
      <description>&lt;p&gt;Imagine adjusting your database schema simply by describing the change in plain English. This is possible by combining &lt;a href="https://docs.anthropic.com/en/docs/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; with the &lt;a href="https://github.com/neondatabase/mcp-server-neon" rel="noopener noreferrer"&gt;Neon MCP Server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This guide demonstrates how to use Claude Code's command-line interface and Neon's MCP server to perform database migrations in your Neon project.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
The Neon MCP Server grants powerful database management capabilities through natural language requests. &lt;strong&gt;Always review and authorize actions requested by the LLM before execution.&lt;/strong&gt; Ensure that only authorized users and applications have access to the Neon MCP Server.&lt;/p&gt;

&lt;p&gt;The Neon MCP Server is intended for local development and IDE integrations only. &lt;strong&gt;We do not recommend using the Neon MCP Server in production environments.&lt;/strong&gt; It can execute powerful operations that may lead to accidental or unauthorized changes.&lt;/p&gt;

&lt;p&gt;For more information, see &lt;a href="https://neon.com/docs/ai/neon-mcp-server#mcp-security-guidance" rel="noopener noreferrer"&gt;MCP security guidance&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Key components
&lt;/h2&gt;

&lt;p&gt;Let's break down the key components in this setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;: Claude Code is Anthropic's official CLI tool that supports Model Context Protocol (MCP) for interfacing with external tools (APIs, databases, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Neon MCP Server&lt;/strong&gt;: Neon's MCP server acts as a bridge between MCP clients like Claude Code and &lt;a href="https://api-docs.neon.tech/reference/getting-started-with-neon-api" rel="noopener noreferrer"&gt;Neon's API&lt;/a&gt;, letting you work with Neon databases using natural language commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;: MCP is a lightweight communication standard that allows Claude Code and Neon MCP Server to work together.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up Neon MCP Server in Claude Code
&lt;/h2&gt;

&lt;p&gt;You have two options for connecting Claude Code to the Neon MCP Server:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remote MCP Server (Preview):&lt;/strong&gt; Connect to Neon's managed MCP server using OAuth for authentication. This method is more convenient as it eliminates the need to manage API keys in Claude Code. Additionally, you will automatically receive the latest features and improvements as soon as they are released.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local MCP Server:&lt;/strong&gt; Run the Neon MCP server locally on your machine, authenticating with a Neon API key.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code:&lt;/strong&gt; Ensure you have Claude Code installed. Visit &lt;a href="https://docs.anthropic.com/en/docs/claude-code" rel="noopener noreferrer"&gt;docs.anthropic.com/en/docs/claude-code&lt;/a&gt; for installation instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon API Key (for Local MCP server):&lt;/strong&gt; After signing up, get your Neon API Key from the &lt;a href="https://console.neon.tech/app/settings/api-keys" rel="noopener noreferrer"&gt;Neon console&lt;/a&gt;. This API key is needed to authenticate your application with Neon. For instructions, see &lt;a href="https://neon.com/docs/manage/api-keys" rel="noopener noreferrer"&gt;Manage API keys&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;br&gt;
   Keep your Neon API key secure, and never share it publicly. It provides access to your Neon projects.&lt;br&gt;
   &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Node.js (&amp;gt;= v18) and npm:&lt;/strong&gt; Ensure Node.js (version 18 or later) and npm are installed. Download them from &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Option 1: Setting up the Remote Hosted Neon MCP Server
&lt;/h3&gt;

&lt;p&gt;Note: By default, the Remote MCP Server connects to your personal Neon account. To connect to an organization's account, you must authenticate with an API key. For more information, see &lt;a href="https://neon.com/docs/ai/neon-mcp-server#api-key-based-authentication" rel="noopener noreferrer"&gt;API key-based authentication&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This method uses Neon's managed server and OAuth authentication.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your terminal.&lt;/li&gt;
&lt;li&gt;Add the Neon MCP server to Claude Code with the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http neon https://mcp.neon.tech/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start a new session of &lt;code&gt;claude&lt;/code&gt; to trigger the OAuth authentication flow:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;You can also trigger authentication with &lt;code&gt;/mcp&lt;/code&gt; within Claude Code.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;If you prefer to authenticate using a Neon API key, provide the &lt;code&gt;Authorization&lt;/code&gt; header to the &lt;code&gt;mcp add&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http neon https://mcp.neon.tech/mcp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;YOUR_NEON_API_KEY&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;YOUR_NEON_API_KEY&amp;gt;&lt;/code&gt; with your actual Neon API key which you obtained from the prerequisites section.&lt;/p&gt;



&lt;p&gt;&lt;br&gt;
The remote hosted MCP server is in preview due to the &lt;a href="https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/authorization/" rel="noopener noreferrer"&gt;new OAuth MCP specification&lt;/a&gt;, expect potential changes as we continue to refine the OAuth integration.&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Setting up the Local Neon MCP Server
&lt;/h3&gt;

&lt;p&gt;This method runs the Neon MCP server locally on your machine, using a Neon API key for authentication.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your terminal.&lt;/li&gt;
&lt;li&gt;Add the Neon MCP server to Claude Code with the following command, replacing &lt;code&gt;&amp;lt;YOUR_NEON_API_KEY&amp;gt;&lt;/code&gt; with your actual Neon API key:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   claude mcp add neon &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @neondatabase/mcp-server-neon start &lt;span class="s2"&gt;"&amp;lt;YOUR_NEON_API_KEY&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;lt;YOUR_NEON_API_KEY&amp;gt;&lt;/code&gt; with your actual Neon API key which you obtained from the prerequisites section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Start a new Claude Code session with the &lt;code&gt;claude&lt;/code&gt; command and start using the Neon MCP server:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You've now configured the Neon MCP Server in Claude Code and can manage your Neon Postgres databases using AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;p&gt;Now that you have the Neon MCP server set up either remotely or locally, you can verify the connection and test the available tools.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start Claude Code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;/mcp&lt;/code&gt; to see the available MCP servers and tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try out a Neon MCP Server tool by typing a query like &lt;code&gt;List my Neon projects&lt;/code&gt; to see your projects and verify the connection.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Supported Actions (Tools)
&lt;/h2&gt;

&lt;p&gt;The Neon MCP Server provides the following actions, which are exposed as "tools" to MCP Clients. You can use these tools to interact with your Neon projects and databases using natural language commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project management:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;list_projects&lt;/code&gt;: Retrieves a list of your Neon projects, providing a summary of each project associated with your Neon account. Supports limiting the number of projects returned (default: 10).&lt;br&gt;
&lt;code&gt;describe_project&lt;/code&gt;: Fetches detailed information about a specific Neon project, including its ID, name, and associated branches and databases.&lt;br&gt;
&lt;code&gt;create_project&lt;/code&gt;: Creates a new Neon project in your Neon account. A project acts as a container for branches, databases, roles, and computes.&lt;br&gt;
&lt;code&gt;delete_project&lt;/code&gt;: Deletes an existing Neon project and all its associated resources.&lt;br&gt;
&lt;code&gt;list_organizations&lt;/code&gt;: Lists all organizations that the current user has access to. Optionally filter by organization name or ID using the search parameter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Branch management:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;create_branch&lt;/code&gt;: Creates a new branch within a specified Neon project. Leverages Neon's branching feature for development, testing, or migrations.&lt;br&gt;
&lt;code&gt;delete_branch&lt;/code&gt;: Deletes an existing branch from a Neon project.&lt;br&gt;
&lt;code&gt;describe_branch&lt;/code&gt;: Retrieves details about a specific branch, such as its name, ID, and parent branch.&lt;br&gt;
&lt;code&gt;list_branch_computes&lt;/code&gt;: Lists compute endpoints for a project or specific branch, including compute ID, type, size, and autoscaling information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQL query execution:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;get_connection_string&lt;/code&gt;: Returns your database connection string.&lt;br&gt;
&lt;code&gt;run_sql&lt;/code&gt;: Executes a single SQL query against a specified Neon database. Supports both read and write operations.&lt;br&gt;
&lt;code&gt;run_sql_transaction&lt;/code&gt;: Executes a series of SQL queries within a single transaction against a Neon database.&lt;br&gt;
&lt;code&gt;get_database_tables&lt;/code&gt;: Lists all tables within a specified Neon database.&lt;br&gt;
&lt;code&gt;describe_table_schema&lt;/code&gt;: Retrieves the schema definition of a specific table, detailing columns, data types, and constraints.&lt;br&gt;
&lt;code&gt;list_slow_queries&lt;/code&gt;: Identifies performance bottlenecks by finding the slowest queries in a database. Requires the pg_stat_statements extension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database migrations (schema changes)&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;prepare_database_migration&lt;/code&gt;: Initiates a database migration process. Critically, it creates a temporary branch to apply and test the migration safely before affecting the main branch.&lt;br&gt;
&lt;code&gt;complete_database_migration&lt;/code&gt;: Finalizes and applies a prepared database migration to the main branch. This action merges changes from the temporary migration branch and cleans up temporary resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query performance tuning:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;explain_sql_statement&lt;/code&gt;: Analyzes a SQL query and returns detailed execution plan information to help understand query performance.&lt;br&gt;
&lt;code&gt;prepare_query_tuning&lt;/code&gt;: Identifies potential performance issues in a SQL query and suggests optimizations. Creates a temporary branch for testing improvements.&lt;br&gt;
&lt;code&gt;complete_query_tuning&lt;/code&gt;: Finalizes and applies query optimizations after testing. Merges changes from the temporary tuning branch to the main branch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neon Auth:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;provision_neon_auth&lt;/code&gt;: Provisions Neon Auth for a Neon project. Sets up authentication infrastructure by creating an integration with Stack Auth (&lt;a class="mentioned-user" href="https://dev.to/stackframe"&gt;@stackframe&lt;/a&gt;/stack).&lt;br&gt;
These actions enable any MCP client like Claude Code to interact with various functionalities of the Neon platform via the Neon API. Certain tools, especially database migration ones, are tailored for AI agent and LLM usage, leveraging Neon's branching for safe preview and commit.&lt;/p&gt;

&lt;p&gt;These actions enable any MCP client like Claude Code to interact with various functionalities of the &lt;strong&gt;Neon platform via the Neon API.&lt;/strong&gt; Certain tools, especially database migration ones, are tailored for AI agent and LLM usage, leveraging Neon's branching for safe preview and commit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Development Workflow: Adding a Column with Claude Code and Neon MCP
&lt;/h2&gt;

&lt;p&gt;Let's walk through a typical development scenario: Quickly adding a column for prototyping using natural language within Claude Code. The following chat log demonstrates a real interaction with Claude Code and the Neon MCP server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; During development, you decide to track timestamps for entries in your &lt;code&gt;playing_with_neon&lt;/code&gt; table. You want to quickly add a &lt;code&gt;created_at&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
For your security, review the tool's purpose before permitting the operation to proceed. Remember that LLMs can sometimes produce unexpected results, so careful monitoring is always recommended.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Here's the conversation log between the user and Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: In my neon project id: round-salad-44063611 list all the tables
Claude Code: I'll help you list all the tables in your Neon project. I'll use the default database name 'neondb' since none was specified.
&amp;gt; Called MCP Tool (get_database_tables)
&amp;gt; I found one table in your database:
&amp;gt; playing_with_neon (in the public schema)
&amp;gt; Would you like to see more details about this table's structure or perform any other operations with it?

User: Can you show me first 5 rows?
Claude Code: I'll query the first 5 rows from the playing_with_neon table.
&amp;gt; Called MCP Tool (run_sql)
&amp;gt; Here are the first 5 rows from the table. The table has three columns:
&amp;gt; id (sequential numbers)
&amp;gt; name (string values)
&amp;gt; value (decimal numbers)
&amp;gt; Would you like to perform any other operations with this data?

User: can you add a created_at column?
Claude Code: I'll help you add a created_at column to the playing_with_neon table. I'll set it up with a timestamp data type and set it to automatically record the creation time of new rows.
&amp;gt; Called MCP Tool (prepare_database_migration)
&amp;gt; Let me verify the change in the temporary branch to make sure it was applied correctly.
&amp;gt; Called MCP Tool (run_sql)
&amp;gt; I've added the created_at column to the playing_with_neon table in a temporary branch. Would you like to commit this migration to the production branch?
&amp;gt; Migration Details:
&amp;gt; Migration ID: a65babcd-d1cc-401f-89b5-762570570102
&amp;gt; Temporary Branch Name: br-silent-cherry-a1eqrl6i
&amp;gt; Temporary Branch ID: br-silent-cherry-a1eqrl6i
&amp;gt; Migration Result: Success
&amp;gt; Please let me know if you'd like to proceed with applying this change to the production branch.

User: yeah do it
Claude Code: I'll complete the migration and apply the changes to the production branch.
&amp;gt; Called MCP Tool (complete_database_migration)
&amp;gt; The migration has been successfully completed! The created_at column has been added to your table in the production branch, and the temporary branch has been cleaned up.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Natural language interaction:&lt;/strong&gt; You can use simple, conversational English to interact with your database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step-by-step guidance:&lt;/strong&gt; Claude Code confirms each step and provides details like branch names and migration IDs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Tools in Action:&lt;/strong&gt; The underlying MCP tools (&lt;code&gt;get_database_tables&lt;/code&gt;, &lt;code&gt;run_sql&lt;/code&gt;, &lt;code&gt;prepare_database_migration&lt;/code&gt;, &lt;code&gt;complete_database_migration&lt;/code&gt;) illustrate the automated process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branching for safety:&lt;/strong&gt; The agent automatically creates a temporary branch for schema changes. The user will be prompted to confirm the migration before applying it to the production branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can verify the changes in your Neon Console or by querying the database directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Creating a project and branch
&lt;/h2&gt;

&lt;p&gt;Beyond schema changes, you can also manage your Neon projects and branches directly within Claude Code using natural language commands. This can be useful for quickly setting up a new development or test environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new project
&lt;/h3&gt;

&lt;p&gt;Let's say you want to create a new Neon project named "my-new-project". You can simply tell Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: Create a Neon project named "my-new-project"
Claude Code: I'll help you create a new Neon project with the specified name.
&amp;gt; Called MCP Tool (create_project)
&amp;gt; Great! I've created a new Neon project for you with the name "my-new-project". Here are the important details:
&amp;gt; Project ID: orange-dawn-33739962
&amp;gt; Default branch: main
&amp;gt; Default database: neondb
&amp;gt; The project is ready to use. You can start creating tables and working with your database right away.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code will then use the &lt;code&gt;create_project&lt;/code&gt; MCP tool to initiate the project creation. It will provide you with a project ID and name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a New Branch
&lt;/h3&gt;

&lt;p&gt;Once you have a project, you can easily create new branches for development or experimentation. For example, to create a branch named "feature-x" in your "my-new-project" project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: Create a branch named "feature-x"
Claude Code: Perfect! I've created a new branch named "feature-x". Here are the details:
&amp;gt; Branch ID: br-cold-mountain-a523ka2w
&amp;gt; Branch name: feature-x
&amp;gt; Parent branch ID: br-odd-pine-a5y53krm
&amp;gt; The branch has been created successfully and is ready for use.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code will use the &lt;code&gt;create_branch&lt;/code&gt; MCP tool to create the branch and provide you with the branch name and ID. Notice how we don't need to specify the project ID, as Claude Code remembers the active project context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Claude Code combined with the Neon MCP Server, whether using the &lt;strong&gt;Remote Hosted (Preview)&lt;/strong&gt; option or the &lt;strong&gt;Local Server&lt;/strong&gt; setup, lets you use natural language to interact with your database and take advantage of Neon's branching capabilities for fast iteration. This approach is ideal for quickly testing database ideas and making schema changes during development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.org" rel="noopener noreferrer"&gt;MCP Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.anthropic.com/en/docs/claude-code" rel="noopener noreferrer"&gt;Claude Code Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.com/docs" rel="noopener noreferrer"&gt;Neon Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.com/docs/manage/api-keys#creating-api-keys" rel="noopener noreferrer"&gt;Neon API Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/neondatabase/mcp-server-neon" rel="noopener noreferrer"&gt;Neon MCP server GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;



</description>
    </item>
    <item>
      <title>Fixing TypeScript Dates</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Sun, 14 Jan 2024 18:27:57 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/fixing-typescript-dates-3fjf</link>
      <guid>https://forem.com/pffigueiredo/fixing-typescript-dates-3fjf</guid>
      <description>&lt;p&gt;Dates formats and timezones have for many years and probably for many more to come, been the nightmare of many developers and also the root of a lot of bugs in very different systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dates in TypeScript
&lt;/h2&gt;

&lt;p&gt;By typing a variable as &lt;code&gt;Date&lt;/code&gt; in TypeScript you are defining that:&lt;/p&gt;

&lt;p&gt;1- it is an &lt;code&gt;object&lt;/code&gt;&lt;br&gt;
2- it represents a Date&lt;br&gt;
3- it has access to a lot of date-related methods- e.g. &lt;code&gt;getDate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, there are still two &lt;strong&gt;very important&lt;/strong&gt; pieces of information that aren't defined in any way by the type system:&lt;/p&gt;

&lt;p&gt;1 - What's the date's timezone?&lt;br&gt;
2 - What's the date's format?&lt;/p&gt;

&lt;h3&gt;
  
  
  Narrowing dates information
&lt;/h3&gt;

&lt;p&gt;Unfortunately, for the timezone, there isn't much that TypeScript can do for us, because it would be "impossible" for a static analysis tool to understand from a given "date string", which timezone it represents, at least without any further info or complex runtime validation.&lt;/p&gt;

&lt;p&gt;However, for a date's format, &lt;strong&gt;TypeScript can be very helpful&lt;/strong&gt; and provide just enough narrowing for us to validate if a "date string" represents a given format, all within the type system! Here is a brief example of how we could define a type for the European date string format:&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;// European DD/MM/YYYY&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EuropeanDate&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;number&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="s2"&gt;/&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="kr"&gt;number&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="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="kr"&gt;number&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;europeanDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EuropeanDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20/10/2024&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="err"&gt;✅&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Eventually, this may lead to some false positives, like the "MM/DD/YYYY" (American format), but type-wise, those formats are the same, so there isn't much we can do there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dates in Data Contracts
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A data contract outlines how data can get exchanged between two parties.&lt;/em&gt; &lt;a href="https://atlan.com/data-contracts/" rel="noopener noreferrer"&gt;atlan&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Data contracts are in it's essence, a way to communicate what data a given resource is going to deliver and expects to receive.&lt;/p&gt;

&lt;p&gt;In the TypeScript ecosystem, having these contracts well-defined (or even auto-generated) &lt;strong&gt;is a must&lt;/strong&gt;, as a lot of times clients rely on them to make requests and manipulate/present the response data.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;date&lt;/code&gt; types are usually a bit different from the rest of the data, due to their sensibility, they usually need to be passed around in the same format, but how can we know in which format, if the contract is defined like this:&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;CreateTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// date in ISO format (is it?)&lt;/span&gt;
  &lt;span class="nl"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// date in ISO format&lt;/span&gt;
  &lt;span class="nl"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;As you can see above, it's very common that we add comments pointing out what's the actual date format, due to the absence of a better alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enforcing a date format
&lt;/h3&gt;

&lt;p&gt;The most common date format used in IT systems is probably the &lt;code&gt;ISO 8601&lt;/code&gt;, it is a standard date and time representation that ensures consistency and is easily sortable, also, it has very good support across different programming languages and systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic format: &lt;code&gt;YYYY-MM-DD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extended format: &lt;code&gt;YYYY-MM-DDTHH:MM:SS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that ideally, our data contracts would also have all the date fields typed as &lt;code&gt;ISO&lt;/code&gt; somehow.&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;GetTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// date in the ISO format!&lt;/span&gt;
  &lt;span class="nl"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TDateISO&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;h2&gt;
  
  
  Defining the &lt;code&gt;TDateISO&lt;/code&gt; type
&lt;/h2&gt;

&lt;p&gt;The 1st step to have our date field typed properly, is obviously to define a TypeScript &lt;code&gt;type&lt;/code&gt; that represents the &lt;code&gt;ISO 8601&lt;/code&gt; date string format. &lt;/p&gt;

&lt;p&gt;This type was extracted from this &lt;a href="https://gist.github.com/MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054" rel="noopener noreferrer"&gt;gist&lt;/a&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;TYear&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;number&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="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;TMonth&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;number&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="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;TDay&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;number&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="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;THours&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;number&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="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;TMinutes&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;number&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="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;TSeconds&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;number&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="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;TMilliseconds&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;number&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="kr"&gt;number&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="cm"&gt;/**
 * Represent a string like `2021-01-08`
 */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TDateISODate&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;TYear&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;TMonth&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;TDay&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="cm"&gt;/**
 * Represent a string like `14:42:34.678`
 */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TDateISOTime&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;THours&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;TMinutes&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;TSeconds&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;TMilliseconds&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="cm"&gt;/**
 * Represent a string like `2021-01-08T14:42:34.678Z` (format: ISO 8601).
 *
 * It is not possible to type more precisely (list every possible values for months, hours etc) as
 * it would result in a warning from TypeScript:
 *   "Expression produces a union type that is too complex to represent. ts(2590)
 */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TDateISO&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;TDateISODate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;T&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;TDateISOTime&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;Z`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;As stated in the comments in the code block, this isn't bulletproof, but as of right now, it is as far as we can go, type-wise, and it's probably good enough for a data contract where you control both the frontend and the backend of the systems communication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overriding native &lt;code&gt;toISOString&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0gzw0l0ejwl9b42qfjcu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0gzw0l0ejwl9b42qfjcu.png" alt="toIsoString returns string"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above, the native JS &lt;code&gt;Date&lt;/code&gt; prototype &lt;code&gt;toISOString()&lt;/code&gt; isn't ready for this new type that we just created and in fact, it just returns a simple &lt;code&gt;string&lt;/code&gt;. So, we must somehow override its return type.&lt;/p&gt;

&lt;p&gt;Luckily for us, the &lt;code&gt;Date&lt;/code&gt; type is defined in an &lt;code&gt;interface&lt;/code&gt;, and interfaces can be "merged" with other interfaces due to &lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces" rel="noopener noreferrer"&gt;declaration merging&lt;/a&gt; - meaning that we can create a new interface with the same name, and modify the existing types (within certain limits).&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;// add this to any TS module (file with exports/imports)&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * Give a more precise return type to the method `toISOString()`:
   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
   */&lt;/span&gt;
  &lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TDateISO&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;Once that's done, anytime we use the native &lt;code&gt;toISOString&lt;/code&gt;, will result in the &lt;code&gt;TDateISO&lt;/code&gt; that we created in the previous step. 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fv3hergtfjs7ko68wa8gf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fv3hergtfjs7ko68wa8gf.gif" alt="final result with toIsoString override"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;1- Standardize all the data contract's dates' format&lt;br&gt;
2- Setup a new TS type that can represent that date format&lt;br&gt;
3- Change the dates in the contracts to the new type&lt;br&gt;
4- Narrow the return type of the native Date functions, if it applies to your system's date format&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dates don't have an easy time in the TypeScript ecosystem, due to so many different variations in formats and timezones, it is still pretty much impossible to have full type safety.&lt;/p&gt;

&lt;p&gt;However, for date formats, it is already possible to narrow down the types enough, to get a much better and safer Developer Experience.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Splitting and Caching React Chunks</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Sat, 30 Dec 2023 16:42:41 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/splitting-and-caching-react-chunks-4c0c</link>
      <guid>https://forem.com/pffigueiredo/splitting-and-caching-react-chunks-4c0c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;There are only two hard things in Computer Science: &lt;strong&gt;cache invalidation&lt;/strong&gt; and naming things.&lt;/em&gt; - Phil Karlton&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Caching is still today one of the hardest things to get right. Nevertheless, it stands as an indispensable element for optimizing performance in any system, essential for unlocking its full potential.&lt;/p&gt;

&lt;p&gt;For a SPA (Single Page Application), the &lt;em&gt;perfect&lt;/em&gt; caching strategy would be to split our code into 2 different categories: &lt;strong&gt;common chunks&lt;/strong&gt; and &lt;strong&gt;route chunks&lt;/strong&gt;. That way, we could in theory only download the necessary JS/CSS code for a given route and re-use all the common (already cached), parts of the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Chunks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fq46i21d9pc6rsrp7f3fk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fq46i21d9pc6rsrp7f3fk.png" alt="Code Chunks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;"chunk,"&lt;/strong&gt; as defined by &lt;a href="https://webpack.js.org/glossary/#c" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;, refers to the distinct components that collectively form a bundle. In the context of &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;, a bundle serves as the entry point for organizing and encapsulating these individual chunks of code.&lt;/p&gt;

&lt;p&gt;Another property that distinguishes &lt;code&gt;chunks&lt;/code&gt; is their independence, meaning that every one of them will be downloaded as a different source - e.g. a bundle with 4 chunks will lead to 4 &lt;code&gt;HTTP&lt;/code&gt; requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Splitting
&lt;/h2&gt;

&lt;p&gt;To deliver the best experience in a web application, it is crucial that the browser only downloads and executes the bare minimum JS/CSS that's needed for a given page/route and that it progressively downloads and executes the rest as needed.&lt;/p&gt;

&lt;p&gt;To achieve these sorts of optimizations, code bundlers (e.g.  Webpack, Rollup...) tend to provide a way to split chunks per route. This means that for each route visited, there will be a preset of chunks that will be downloaded by the browser, as the user navigates through the different pages/routes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fmhdtkd31iw548duf3px7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fmhdtkd31iw548duf3px7.png" alt="Chunks Downloads"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above we can see a very simplistic view of how navigating into the &lt;code&gt;/page1&lt;/code&gt; route would lead to only downloading the necessary parts - &lt;code&gt;common-chunk.js&lt;/code&gt; and &lt;code&gt;page1-chunk.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identifying the common code
&lt;/h3&gt;

&lt;p&gt;For the most part, bundlers do a "good enough" work by creating multiple independent chunks that can be re-used across a web app, so that users only download the bare minimum that's needed for a given page. Take a quick peek at Webpack &lt;a href="https://webpack.js.org/plugins/split-chunks-plugin/#defaults" rel="noopener noreferrer"&gt;docs&lt;/a&gt; below on when it creates a new chunk automatically:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Webpack will automatically split chunks based on these conditions:

- New chunk can be shared OR modules are from the node_modules folder
- New chunk would be bigger than 20kb (before min+gz)
- Maximum number of parallel requests when loading chunks on demand would be lower or equal to 30
- Maximum number of parallel requests at initial page load would be lower or equal to 30

When trying to fulfill the last two conditions, bigger chunks are preferred.


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

&lt;/div&gt;

&lt;p&gt;However, we can probably do better with very little work, just by looking at our app and understanding which parts of the code we should extract into independent chunks.&lt;/p&gt;

&lt;p&gt;While there is potential to take loads of time to optimize this process, we should probably stick to the ones that will have the most impact on our bundle size and that will be used in most routes, and these usually fall under one of the following categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[related vendors] &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;react-dom&lt;/code&gt; and &lt;code&gt;react-router-dom&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[globally used vendors] &lt;code&gt;lodash&lt;/code&gt;, &lt;code&gt;css-in-js&lt;/code&gt; lib, etc...&lt;/li&gt;
&lt;li&gt;[global styles] &lt;code&gt;CSS Reset&lt;/code&gt; files, &lt;code&gt;global styles&lt;/code&gt; files, etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extracting common parts into chunks
&lt;/h3&gt;

&lt;p&gt;Once we have identified all the common parts of code we want to extract into independent chunks, it's usually very straightforward to actually set this up in whatever bundler you are using. &lt;/p&gt;

&lt;p&gt;Here is an example of how we could create a new chunk for all the &lt;code&gt;react&lt;/code&gt; related vendors using &lt;code&gt;webpack&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&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="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;cacheGroups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;reactVendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/](&lt;/span&gt;&lt;span class="sr"&gt;react|react-dom|react-router-dom&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vendor-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&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;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;This Webpack config uses &lt;code&gt;splitChunks&lt;/code&gt; combined with &lt;code&gt;cacheGroups&lt;/code&gt; to create specific code chunks that pass the given &lt;code&gt;test&lt;/code&gt; regex:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;reactVendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/](&lt;/span&gt;&lt;span class="sr"&gt;react|react-dom|react-router-dom&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vendor-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;After we apply this change to the config, Webpack will generate a new chunk that will include any code that comes from &lt;code&gt;react&lt;/code&gt;, &lt;code&gt;react-dom&lt;/code&gt;, or &lt;code&gt;react-router-dom&lt;/code&gt;, with the name &lt;code&gt;reactVendor.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The last step to get this working, is to include this newly produced asset in our HTML file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./vendor-react.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Since we need &lt;code&gt;React&lt;/code&gt; to run our application, it's better to include it on the &lt;code&gt;head&lt;/code&gt; tag, so it's picked up faster by the browser. &lt;/p&gt;

&lt;p&gt;However, to fully leverage this new chunk, it's &lt;strong&gt;crucial to configure caching&lt;/strong&gt;, ensuring it is downloaded only once and subsequently "reused" across all page navigations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching Static Assets (Chunks)
&lt;/h2&gt;

&lt;p&gt;To efficiently cache static assets, there are certain aspects we need to take into consideration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what's the best strategy&lt;/li&gt;
&lt;li&gt;when to invalidate the cache&lt;/li&gt;
&lt;li&gt;how to invalidate the cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my opinion, the best way to cache static assets is a combination of &lt;strong&gt;CDN distribution&lt;/strong&gt; with &lt;strong&gt;cache busting&lt;/strong&gt;, so that's what we will discuss below.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN Distribuition
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fm9p6ujt0ol7xcyotc3v9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fm9p6ujt0ol7xcyotc3v9.png" alt="CDN Distrtibution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A content delivery network (CDN) is a geographically distributed group of servers that caches content close to end users. A CDN allows for the quick transfer of assets needed for loading Internet content, including HTML pages, JavaScript files, stylesheets, images, and videos.&lt;/em&gt; - &lt;a href="https://www.cloudflare.com/en-gb/learning/cdn/what-is-a-cdn/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The CDN will be 1st opportunity for caching, since that's the system that we will be hitting when visiting a web app for the first time. Bear in mind that it will not, prevent the consumers of a web app from downloading the assets (that's the browser's work), but it will make the load time much faster by placing the static assets closer to the user's device, at least, once they are cached.&lt;/p&gt;

&lt;p&gt;Enabling cache for CDNs is usually well-defined within their docs, but the most common practice is setting the &lt;code&gt;Cache-Control&lt;/code&gt; header to &lt;code&gt;public&lt;/code&gt; and &lt;code&gt;max-age&lt;/code&gt; with a value greater than 0, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Cache-Control: max-age=31536000,immutable


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

&lt;/div&gt;

&lt;p&gt;The best/simpler practice in this regard would be to add the &lt;code&gt;Cache-Control&lt;/code&gt; header to every single asset BUT the ones that are NOT created by the bundler, meaning: &lt;code&gt;.html&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.gif&lt;/code&gt;... And that's just because they don't pass by a bundling process that allows us to change their name depending on the content.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN Cache Invalidation
&lt;/h3&gt;

&lt;p&gt;Invalidating the cache is a very sensible process and as such, it should be as straightforward as possible, so that we can minimize errors, such as delivering outdated assets.&lt;/p&gt;

&lt;p&gt;The simplest and most effective strategy for this is to invalidate the cache every time we make a make a new deployment, for all the assets that are not part of our bundling process, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.html&lt;/li&gt;
&lt;li&gt;.png&lt;/li&gt;
&lt;li&gt;.jpg&lt;/li&gt;
&lt;li&gt;.gif&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And this is simply because even if these assets change, they can still keep the same name and we don't really have a way to signalize the CDN if they are outdated or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Busting
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5kb7ajl88t4ymr21kzc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5kb7ajl88t4ymr21kzc3.png" alt="Cache Busting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Cache busting is a technique used by web developers to force the browser to load the most recent version of a file, rather than a previously cached version.&lt;/em&gt; - &lt;a href="https://www.keycdn.com/support/what-is-cache-busting" rel="noopener noreferrer"&gt;keyCDN&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We still need to somehow signalize both the CDN and the Browser if we should get a new asset or re-use the cached one. And the best way to do that is through &lt;code&gt;cache busting&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cache busting can be applied with different strategies, such as:&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;// File name versioning&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.v2.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// File path versioning&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/v2/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Query params versioning&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.js?v=2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// File content hashing&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[name].[contenthash].js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  File content hashing
&lt;/h3&gt;

&lt;p&gt;From my experience, &lt;strong&gt;content hashing&lt;/strong&gt; is the best &lt;code&gt;cache busting&lt;/code&gt; strategy for 3 reasons:&lt;/p&gt;

&lt;p&gt;1- we don't rely on past data (like in versioning)&lt;br&gt;
2- we can still use cached assets even after new deployments&lt;br&gt;
3- cache busting is done automatically by having differently named files when their content changes&lt;/p&gt;

&lt;p&gt;In Webpack, to generate the chunk names using their content hashes, we  can change the output format like so:&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;// webpack config&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/app.js&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="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// entry bundle chunks names&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].[contenthash].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 🆕&lt;/span&gt;
    &lt;span class="c1"&gt;// non-initial chunk names&lt;/span&gt;
    &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].[contenthash].bundle.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 🆕&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// removes old bundles from the directory&lt;/span&gt;
    &lt;span class="na"&gt;clean&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="c1"&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;Once we build our web app with such configuration, we will have something similar to this:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;📁 dist/&lt;br&gt;
 ├── 📄 index.html&lt;br&gt;
 ├── 📄 app.575d644de9307ca8621d.js&lt;br&gt;
 └── 📄 vendor-react.7c8b137d61bff5cad6e7.bundle.js&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Summary&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;1- Extract common parts of code into their own chunks;&lt;br&gt;
2- Distribute your web app through a CDN;&lt;br&gt;
3- Invalidate non-bundled assets on deployment;&lt;br&gt;
4- Setup a caching strategy through cache busting;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;Make sure to take a look at these sources if you wanna have a more in-depth understanding of caching and code splitting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.codemzy.com/blog/react-bundle-size-webpack-code-splitting" rel="noopener noreferrer"&gt;Reduce your react bundle size with webpack code splitting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.codemzy.com/blog/cache-busting-react" rel="noopener noreferrer"&gt;Cache busting a React app for production&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Distributing cached assets is the best way to spare the clients from downloading unnecessary code and having a much faster loading time. &lt;/p&gt;

&lt;p&gt;One of the best ways to do it is by distributing your web app through a CDN and setting up a strategy that allows for invalidating new assets when their content changes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Making lodash tree-shakable</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Sun, 19 Nov 2023 19:23:30 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/making-lodash-tree-shakable-3h27</link>
      <guid>https://forem.com/pffigueiredo/making-lodash-tree-shakable-3h27</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1- Replace `lodash` with `lodash-es`
2- Ditch default imports
3- Prefer namespace imports - import * as _ from "lodash-es"
4- Setup a linter rule to not allow this happen again
5- See great bundle size improvements 😎  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lodash
&lt;/h2&gt;

&lt;p&gt;Lodash is a JS utility library that delivers small functions capable of easing the way we work with arrays, numbers, objects, strings, etc. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isEmpty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lowerCase&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;concat&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And although it's about 11 years old, &lt;code&gt;lodash&lt;/code&gt; is still today, the most "depended-upon" package, according to the &lt;a href="https://gist.github.com/anvaka/8e8fa57c7ee1350e3491"&gt;npm registry&lt;/a&gt;. So it's very likely that you are using it directly or indirectly through one of your dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  CommonJS
&lt;/h3&gt;

&lt;p&gt;When &lt;code&gt;lodash&lt;/code&gt; was first introduced in 2011, &lt;code&gt;CommonJS&lt;/code&gt; was the common standard to write JS modules, however, that standard was mainly intended to be used in server-side applications and never to reach the browser.&lt;/p&gt;

&lt;p&gt;But in 2023, the &lt;code&gt;lodash&lt;/code&gt; library is still being widely used in web applications, and of course, it's still written in the &lt;code&gt;CommonJS&lt;/code&gt; format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tree Shaking in CommonJS
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Tree shaking is a process in modern JavaScript bundlers that eliminates unused code during the build process, resulting in smaller and more optimized bundles.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because &lt;code&gt;CommonJS&lt;/code&gt; was originally designed with server-side applications in mind, it didn't prioritize a crucial aspect for browser-based environments: &lt;strong&gt;the ability to be tree shaken&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This happens because CommonJS allows for highly dynamic imports/exports, that bundlers can't simply pick up and do a fully static analysis on, to understand if certain code should be kept or eliminated in the final bundle.&lt;/p&gt;

&lt;p&gt;For more in-depth information on how &lt;code&gt;CommonJS&lt;/code&gt; works when it comes to tree shaking, make sure to take a look at this great &lt;a href="https://web.dev/articles/commonjs-larger-bundles"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Tree-Shakable Alternative
&lt;/h3&gt;

&lt;p&gt;In today's web development, &lt;code&gt;ECMAScript&lt;/code&gt; is the go-to standard for writing JS modules and it's being widely adapted not only on the browser but also on &lt;code&gt;node&lt;/code&gt; environments. &lt;/p&gt;

&lt;p&gt;This standard is much more mature and offers much better support for static analysis and tree shaking due to its more declarative and static nature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tree-shaking &lt;code&gt;lodash&lt;/code&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Now that we have gone through why tree shaking doesn't play well with &lt;code&gt;lodash&lt;/code&gt;, let's dive into what we can do we make it tree-shakable.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;1- Replacing &lt;code&gt;lodash&lt;/code&gt; with &lt;code&gt;lodash-es&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Due to the huge amount of benefits of using ESM (ECMAScript Modules), the &lt;a href="https://www.npmjs.com/package/lodash-es"&gt;&lt;code&gt;lodash-es&lt;/code&gt;&lt;/a&gt; lib was created and it's now the recommended package to be installed if you want to continue to use &lt;code&gt;lodash&lt;/code&gt;, it is still the same library, but exported as ES modules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2- Stop using the default import&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another very common practice that might completely ruin tree shaking, is doing a default import when using &lt;code&gt;lodash&lt;/code&gt; or any other lib that exports everything from the default exported variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash-es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// `_` contains every single lodash's function &lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpy&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowerCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HEY&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;In the example above, although we are only using 3 functions, we are actually importing the whole lib, because the &lt;code&gt;default&lt;/code&gt; export is an object that contains all the lib's utilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3- Use namespace imports&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Namespace imports are a way to import every single exported member from a module individually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash-es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// `_` contains every single lodash's function &lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpy&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lowerCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HEY&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 difference between this and the &lt;code&gt;default&lt;/code&gt; import, is that we are importing &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;isEmpty&lt;/code&gt; and &lt;code&gt;lowerCase&lt;/code&gt; individually and as such, every other import that isn't used will be removed at build time.&lt;/p&gt;

&lt;p&gt;Of course, you could also import each utility individually, but because of how similar these function names are to the ones provided by native JS, I highly recommend that you keep the &lt;code&gt;_&lt;/code&gt; prefix when using &lt;code&gt;lodash&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash-es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// makes it harder to understand which one is each ❌&lt;/span&gt;
&lt;span class="nf"&gt;some&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ------------------------------------------------&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash-es&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// makes it very easy to understand which one is each ✅&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus tip
&lt;/h3&gt;

&lt;p&gt;To safeguard against unintentional slip-ups, such as default imports that can bloat your app's bundle size, I strongly recommend incorporating an ESLint rule to NOT allow using the &lt;code&gt;default&lt;/code&gt; import of &lt;code&gt;lodash-es&lt;/code&gt;.&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;// eslintrc.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rules&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;no-restricted-syntax&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="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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not import default from lodash-es. Use a namespace import (* as) instead.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ImportDeclaration[source.value="lodash-es"] ImportDefaultSpecifier&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;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;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1- Avoid using CommonJS libraries in browser-based applications&lt;br&gt;
2- Be mindful when using default imports and prefer namespace imports&lt;br&gt;
3- Avoid these common pitfalls with linter rules&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This approach is not exclusive to &lt;code&gt;lodash&lt;/code&gt;, and it can actually be applied to a variety of packages, particularly those that are still being exported as &lt;code&gt;CommonJS&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>TypeScript Return Types: Separating Fact from Fiction</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Mon, 13 Feb 2023 00:21:20 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/typescript-return-types-separating-fact-from-fiction-4266</link>
      <guid>https://forem.com/pffigueiredo/typescript-return-types-separating-fact-from-fiction-4266</guid>
      <description>&lt;h2&gt;
  
  
  TypeScript Return Types
&lt;/h2&gt;

&lt;p&gt;This subject has been trending a lot on &lt;a href="https://twitter.com/theprimeagen/status/1620808334562697217?s=46&amp;amp;t=z0_DjF4Ri7xIhYEap0PQ0Q"&gt;Twitter&lt;/a&gt; lately and there have been a lot of discussions, videos and different views around that topic. &lt;/p&gt;

&lt;p&gt;It's a topic that sparks different perspectives based on one's background and approach to coding. Some may prefer to focus on the practical aspect, while others might lean more toward the theoretical side.&lt;/p&gt;

&lt;p&gt;Let's just say that in the end, there are no rights or wrongs and it's not something you or I should be spending much time thinking about.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript Inference
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;...type inference is used to provide type information when there is no explicit type annotation&lt;/em&gt; - &lt;a href="https://www.typescriptlang.org/docs/handbook/type-inference.html"&gt;TS docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TypeScript being smart and being able to infer a function's return type without any hints, really is the only reason why this discussion even exists.&lt;/p&gt;

&lt;p&gt;This doesn't mean that we should solely rely on TypeScript's type inference, as there are situations where explicitly defining the types is certainly the best approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript Functions
&lt;/h3&gt;

&lt;p&gt;Another reason for this discussion stems from the fact that many developers from various backgrounds, not just frontend and TypeScript, have a habit of defining contracts or interfaces first when coding.&lt;/p&gt;

&lt;p&gt;However, the current frontend scene is quite different. It focuses on &lt;strong&gt;functional programming&lt;/strong&gt; with a touch of composability, leading to a lot of small and well-defined functions that can be easily combined to achieve more complex tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infer by default
&lt;/h2&gt;

&lt;p&gt;If you are building a TS based product, chances are that you have a lot of small and simple functions that are self explanatory like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getName&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getAge&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getUser&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canRemoveItem&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onModalOpen&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By looking at the names of those functions, you can easily &lt;strong&gt;deduce their return type&lt;/strong&gt;. If the return type is not what you expect, it's likely not the type that needs to be changed, but rather the function name itself.&lt;/p&gt;

&lt;p&gt;This means that by default, a simple and well defined function shouldn't need explicit return types, it should be implicit by its semantics, or in other words, &lt;strong&gt;inferred&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of inferring
&lt;/h3&gt;

&lt;p&gt;Relying on inferred return types not only simplifies the process, but it also brings several key benefits, including: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Development Speed&lt;/strong&gt;&lt;br&gt;
Avoiding the need to define return types for small functions and reducing the need to revisit them as code grows leads to faster software development with equal quality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Maintainability&lt;/strong&gt;&lt;br&gt;
Defining return types add extra code that must be maintained, potentially leading to adjustments for small functions with well-defined boundaries, resulting in unnecessary complexity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source of Truth&lt;/strong&gt;&lt;br&gt;
When you rely on the inferred return type, the source of truth will always lay on your code's implementation, whatever you return, will always stick as the return type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same, however, isn't true if you implicitly define it, as you can "easily" override the correct return type by mistake:&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;Animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnimal&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Animal&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;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Joey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;// TS accepts this property, but Animal doesn't have it ❌&lt;/span&gt;
        &lt;span class="na"&gt;breed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Boxer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to use Return Types
&lt;/h3&gt;

&lt;p&gt;If by default we should allow inference to do the dirty work, then, in which situations should we be explicitly defining a function's return types?&lt;/p&gt;

&lt;p&gt;There are actually some situations where it's useful to define it and more than not, it is related to the function's own complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Narrowing return types&lt;/strong&gt;&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;SuccessAction&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="na"&gt;type&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_FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;payload&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;successAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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;SuccessAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&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_FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;payload&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 common scenario, is when you define "action creator" functions that return a store's action (Redux or not).&lt;/p&gt;

&lt;p&gt;There are actually 2 reasons to define the return type here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If we don't define it, the &lt;code&gt;type&lt;/code&gt; property will be &lt;code&gt;string&lt;/code&gt; instead of the literal &lt;code&gt;"SUCCESS_FETCH"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It makes way more sense to see &lt;code&gt;SuccessAction&lt;/code&gt; as the return type, instead of just a "random" object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;2. Multiple code branches&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's very common for functions to get big and complex and with a lot of code branches that may lead to different return types. &lt;/p&gt;

&lt;p&gt;If that's the case, you will &lt;strong&gt;NOT&lt;/strong&gt; want to see a bunch of unions of different return types on your screen.&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;Action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSE_TODO&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;CREATE_TODO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This leads to a pretty loose union of return types ❌&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSE_TODO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;closed&lt;/span&gt;&lt;span class="dl"&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="na"&gt;closedTimestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CREATE_TODO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;new&lt;/span&gt;&lt;span class="dl"&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="na"&gt;createTimeStamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the sample of code above, it's easy to understand that the more code branches, the more possibilities there are to return the wrong thing, even more if the return type changes depending on some condition (like this case).&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;// with defined return type ✅&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TodoSate&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;closed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;closedTimestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="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;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createTimeStamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSE_TODO&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;CREATE_TODO&lt;/span&gt;&lt;span class="dl"&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;handleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;TodoSate&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSE_TODO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;closed&lt;/span&gt;&lt;span class="dl"&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="na"&gt;closedTimestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CREATE_TODO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;new&lt;/span&gt;&lt;span class="dl"&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="na"&gt;createTimeStamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Defining the return type in these sorts of scenarios, can have major advantages such as:&lt;/p&gt;

&lt;p&gt;1- Not allowing impossible states, like having the status &lt;code&gt;open&lt;/code&gt; and the &lt;code&gt;closedTimestamp&lt;/code&gt; defined.&lt;br&gt;
2- Not allowing typos in any of the returned objects.&lt;br&gt;
3- It's much more scalable as the functions grow in size/complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Library's code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For library's code, however, the story is much different when it comes to return types. The main rule here is, for every function that is being publicly exposed, you should define the return type and the reasons are pretty simple:&lt;/p&gt;

&lt;p&gt;1- Consumers should be able to import and utilize the return type of a function in order to effectively reuse and compose the library's functionalities.&lt;br&gt;
2- Having a well-defined return type "name" saves developers time and eliminates the need to constantly refer to type definition files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When using TypeScript for development, it's best to rely on inferred return types and only define them in specific cases. This approach leads to faster development and reduces the risk of errors, improving both speed and reliability of your code.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>2 NEW killer features coming to TypeScript</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Thu, 05 May 2022 23:16:13 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/2-new-killer-features-coming-to-typescript-3b5j</link>
      <guid>https://forem.com/pffigueiredo/2-new-killer-features-coming-to-typescript-3b5j</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2F3mkkpj3r8nfoec68jf0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3mkkpj3r8nfoec68jf0b.png" alt="New TS features"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript 4.7
&lt;/h2&gt;

&lt;p&gt;This &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta" rel="noopener noreferrer"&gt;upcoming TypeScript version&lt;/a&gt; will bring a lot of new features and improvements to the language, but there are &lt;strong&gt;2 in particular&lt;/strong&gt; that I found especially interesting:&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions" rel="noopener noreferrer"&gt;Instatiation Expressions&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;2- &lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions" rel="noopener noreferrer"&gt;&lt;code&gt;extends&lt;/code&gt; Constraints on &lt;code&gt;infer&lt;/code&gt; Type Variables&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New features value
&lt;/h3&gt;

&lt;p&gt;If you are anything like me and &lt;strong&gt;enjoy creating complex type definitions&lt;/strong&gt; that provide great levels of Developer Experience to you and your co-workers, then you should absolutely &lt;strong&gt;be on top of these new features,&lt;/strong&gt; as they will ease the way you write those type definitions, by A LOT.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce your types &lt;strong&gt;complexity&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Reduce your types &lt;strong&gt;verbosity&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Decrease the amount of &lt;strong&gt;workarounds&lt;/strong&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instantiation Expressions
&lt;/h2&gt;

&lt;p&gt;For anyone that has written more than a handful of generic functions, this new feature is probably something that could have saved you from writing "crappy" JS workarounds to get some types going.&lt;/p&gt;

&lt;p&gt;Instantiation Expressions will allow us to get a generic  type, without the "instantiation" part 🤯&lt;/p&gt;

&lt;h3&gt;
  
  
  Before 4.7:
&lt;/h3&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;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;isGoodBoy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;getBigPet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;big&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 1- Need to have a typed param to pass 👎&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jake&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isGoodBoy&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="c1"&gt;// 2- Need to create an arrow function 👎&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getBigDog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getBigPet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Before this upcoming version, there was really no way to leverage a generic function's type, which led many of us to &lt;strong&gt;create workarounds&lt;/strong&gt; by writing unnecessary JS code. ❌&lt;/p&gt;

&lt;h3&gt;
  
  
  After 4.7
&lt;/h3&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;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;isGoodBoy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;getBigPet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;big&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Can "instantiate" on the fly ✅&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getBigDog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBigPet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Dog&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;// No need to bring in any extra types ✅&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BigCat&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;getBigPet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;So, what &lt;strong&gt;Instantiation Expressions&lt;/strong&gt; bring to the table, is the simplicity with which one can retrieve a generic function's type without any sort of workarounds or creating any extra JS code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No need to write JS code just for the sake of typing;&lt;/li&gt;
&lt;li&gt;The types API gets simplified;&lt;/li&gt;
&lt;li&gt;Leveraging function's &lt;code&gt;ReturnType&lt;/code&gt; just became a first-class citizen;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;extends&lt;/code&gt; Constraints on &lt;code&gt;infer&lt;/code&gt; Type Variables
&lt;/h2&gt;

&lt;p&gt;This new feature is something that will help anyone to write  way less verbose types when depending on inferred type constraints.&lt;/p&gt;

&lt;p&gt;It basically acts as an early &lt;code&gt;return&lt;/code&gt; statement that we (developers), many times use in languages like JavaScript to immediately move away to the "false" logical path, when some conditional is met.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before 4.7
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// A type that returns the First and Last elements of the Number type &lt;/span&gt;

&lt;span class="c1"&gt;// 😔😔😔 This feels overwhelming...&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FirstAndLastNumber&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="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="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="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Tail&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Tail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;]&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="nx"&gt;never&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before this upcoming feature, there was no way to do an "early check" on the inferred types, and because of that, we ended up &lt;strong&gt;creating very verbose and "scary" types&lt;/strong&gt;. ❌&lt;/p&gt;

&lt;h3&gt;
  
  
  After 4.7
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// The "same" type as before 🤯🤯🤯&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FirstAndLastNumber&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="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="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="p"&gt;[&lt;/span&gt;

&lt;span class="c1"&gt;// 1- Add the extends constraint here&lt;/span&gt;
  &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;// 2- Add the extends constraint here&lt;/span&gt;
  &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Tail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tail&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;extends&lt;/code&gt; Constraints on &lt;code&gt;infer&lt;/code&gt; Type Variables&lt;/strong&gt; really simplifies the process of defining types that rely on inferred type variables - more than a syntax change, this feature really takes the mental model of creating types one step closer to the one we use in "real programming".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
1- Cleaner and less verbose types;&lt;br&gt;
2- Lowers the complexity barrier for others to touch this otherwise "monstrosity" type;&lt;br&gt;
3- TypeScript compiler will be faster because it can return earlier;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By taking advantage of TypeScript's 4.7 version new features, you will be able to lower the complexity of type definitions by a lot, making it way easier for anyone to understand and even develop on top of those types. &lt;/p&gt;

&lt;p&gt;P.S. You can already try these new features in the &lt;a href="https://www.typescriptlang.org/play" rel="noopener noreferrer"&gt;TypeScript Playground&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Generics vs Function Overloading vs Union Type Arguments in TypeScript</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Mon, 25 Apr 2022 14:58:06 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/the-typescript-functions-mental-model-1301</link>
      <guid>https://forem.com/pffigueiredo/the-typescript-functions-mental-model-1301</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fyrpntycf9gak3azplaue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fyrpntycf9gak3azplaue.png" alt="Decision diagram on typescript's functions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript Functions
&lt;/h2&gt;

&lt;p&gt;When it comes to writing TypeScript functions, it is possible, that you have experienced this sort of thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This looks kinda weird, should I try this in another way? Maybe &lt;strong&gt;function overloading&lt;/strong&gt;, or perhaps &lt;strong&gt;generics&lt;/strong&gt; would help here. 🤔&lt;/em&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And you ended up changing for one of them, without really knowing if it was the right way.&lt;/p&gt;

&lt;p&gt;I've been there and have certainly done this countless times — but what if there was &lt;strong&gt;a system&lt;/strong&gt; that could help you solve this little nuance? &lt;/p&gt;

&lt;p&gt;That's exactly what I'm presenting here — a system that will allow you to make a &lt;strong&gt;good and consistent&lt;/strong&gt; decision on how you write a TypeScript function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Union Types
&lt;/h2&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;Pet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PetOwner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;PetOwner&lt;/span&gt;&lt;span class="p"&gt;)&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;TypeScript's &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-types" rel="noopener noreferrer"&gt;union types&lt;/a&gt; are super useful when it comes to typing anything that can have multiple type definitions.&lt;/p&gt;

&lt;p&gt;For functions in particular, it is super useful to type its &lt;strong&gt;parameters or return types&lt;/strong&gt;. And you are perhaps using it more than you knew, because every time you define a argument as &lt;code&gt;optional&lt;/code&gt; , it actually becomes &lt;code&gt;type | undefined&lt;/code&gt;, meaning it is a union type underneath!&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;p&gt;When it comes to functions, this is pretty much the most basic strategy for typing its parameters. So my advice is to stick to it whenever possible, but it has more restraints than the others strategies and it doesn't work for more complex scenarios.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;union types&lt;/strong&gt; when:&lt;/p&gt;

&lt;p&gt;1- You are &lt;strong&gt;aware of all the possible members&lt;/strong&gt; of each union type at the moment of the function's declaration;&lt;br&gt;
2- The &lt;strong&gt;return type doesn't change&lt;/strong&gt; depending on the argument's types;&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;Pet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PetOwner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ownerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Don't do this - you will return an ambiguous type ❌&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;PetOwner&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;PetOwner&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;petOrOwner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// You have no idea which will be the array type ❌&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFirstElementArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)[]):&lt;/span&gt; &lt;span class="kr"&gt;any&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;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Also, when using union types for typing functions, you should most likely &lt;strong&gt;not need to type the return type explicitly&lt;/strong&gt;. That's just because the return type shouldn't change at all for this way of doing things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function Overloading
&lt;/h2&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;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Overload signatures&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&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;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Implementation signature&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;surname&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="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;TypeScript's &lt;a href="https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads" rel="noopener noreferrer"&gt;function overloads&lt;/a&gt; is a great way to specify multiple function signatures in a super declarative way, while making each of those have its own type definition, either for the arguments or the return type.&lt;/p&gt;

&lt;p&gt;To leverage this way of typing a function all you need to do is the following:&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Define your functions' possible signatures&lt;/strong&gt; (the different overloads)&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;// Overload signatures&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&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;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;2- &lt;strong&gt;Define your functions implementations&lt;/strong&gt; - this function's signature must be a union over the other previously created functions, so that it respects every single overload.&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;// name - required because it is defined in both overloads&lt;/span&gt;
&lt;span class="c1"&gt;// surname - optional, because it is only present in one of the overloads&lt;/span&gt;

&lt;span class="c1"&gt;// return type - SingleNamePerson | FullNamePerson because it can be either one of those&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;surname&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;p&gt;Function overloading works pretty well with more difficult and dynamic signatures, as it will provide a way to define multiple combinations in a way that is easy to understand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fmr1ii3xf7j1lxbqmirwg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fmr1ii3xf7j1lxbqmirwg.gif" alt="function overloads usage example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;function overloading&lt;/strong&gt; when:&lt;/p&gt;

&lt;p&gt;1- You are &lt;strong&gt;aware of all the possible members&lt;/strong&gt; of each union type at the moment of the function's declaration;&lt;br&gt;
2- The &lt;strong&gt;return type changes&lt;/strong&gt; depending on the argument's types;&lt;br&gt;
3- The &lt;strong&gt;return type isn't a direct mapping&lt;/strong&gt; of the provided parameters;&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;// Don't do this ❌ - the return type is a direct mapping of the provided argument (use a generic instead)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&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;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&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;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;person&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;surname&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Generic Functions
&lt;/h2&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;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;singleNamePerson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SingleNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullNamePerson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FullNamePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PersonT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PersonT&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;singleNamePerson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Return type =&amp;gt; `SingleNamePerson`&lt;/span&gt;
&lt;span class="nf"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullNamePerson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Return type =&amp;gt; `FullNamePerson`&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;TypeScript's &lt;a href="https://www.typescriptlang.org/docs/handbook/2/functions.html#generic-functions" rel="noopener noreferrer"&gt;Generic Functions&lt;/a&gt; is probably &lt;strong&gt;the most versatile way&lt;/strong&gt; to create a function that is dynamic in some way or another.&lt;/p&gt;

&lt;p&gt;It allows you to get &lt;strong&gt;full type support&lt;/strong&gt; on every possible abstraction for a function that deals with very different scenarios (and where you are not fully aware of what may be passed in as an argument ahead of time).&lt;/p&gt;

&lt;p&gt;But all these opportunities and versatility come with a cost.  As generics seem to fit everywhere, &lt;strong&gt;developers tend to overuse them&lt;/strong&gt;, and believe me, no one wants to edit a function surrounded by overly complex generic types, especially if it was written by another engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;p&gt;Generic Functions are the only solution you have to solve the  common problem between union types and function overloading — the capacity of adding type support when we are &lt;strong&gt;not aware of all the possible types&lt;/strong&gt; beforehand.&lt;/p&gt;

&lt;p&gt;Not only that, but Generics are also a great option when the return type of a function is associated with the types of the parameters (even if you are aware of them ahead of time).&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;// Defining the return type based on the argument's type&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFirstElement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirstElement&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// return type =&amp;gt; number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirstElement&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// return type =&amp;gt; string&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirstElement&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="c1"&gt;// return type =&amp;gt; boolean&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Use &lt;strong&gt;generic functions&lt;/strong&gt; when:&lt;br&gt;
1- You are &lt;strong&gt;NOT aware of the argument types&lt;/strong&gt; beforehand;&lt;br&gt;
2- The &lt;strong&gt;return type is a direct mapping&lt;/strong&gt; (or close to it) of the provided parameters;&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
  &lt;span class="nl"&gt;toy&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;br&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
  &lt;span class="nl"&gt;furrballs&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;br&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Turtle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
  &lt;span class="nl"&gt;isMainlyAquatic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;};&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// This can get tricky pretty quickly ❌&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetAnimalReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&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;AnimalT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnimalT&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;feline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turtle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// We need to use type assertions - not ideal ❓&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnimalType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&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;animal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnimalT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;GetAnimalReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canine&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;GetAnimalReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;furrballs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;feline&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;GetAnimalReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turtle&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;GetAnimalReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimalT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Generics vs function overloading&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzzjbc3tifql3azf9xxkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzzjbc3tifql3azf9xxkr.png" alt="generics vs functions overloading example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to choosing between &lt;strong&gt;function overloading&lt;/strong&gt; and &lt;strong&gt;generics&lt;/strong&gt; the line is blurrier and the decision isn't quite clear. As you can observe in the image above, these two feature usage intersects when it comes to typing a function that has known argument types and whose return type depends on those very same arguments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which to choose
&lt;/h3&gt;

&lt;p&gt;The answer will depend on the developer's preference, but my opinion is that to keep things simple you should opt for &lt;code&gt;generics&lt;/code&gt; instead of &lt;code&gt;function overloading&lt;/code&gt; only when this rule applies:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The code that you need to write to define the return type &lt;strong&gt;doesn't have more than 1 level of depth of &lt;code&gt;extends&lt;/code&gt; expressions&lt;/strong&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the rule that I use for myself to keep code consistent and easier for others to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are multiple techniques to write dynamic functions in TypeScript and by applying this "mental model", you will be able to define those functions in a more consistent and clean way, while also making usage of each technique for what it was actually intended. 👇&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unions&lt;/strong&gt; =&amp;gt; Use when return type doesn't change;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function Overloading&lt;/strong&gt; =&amp;gt; Use when you are aware of the argument types and the return type &lt;strong&gt;does change&lt;/strong&gt; depending on the argument types;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generics&lt;/strong&gt; =&amp;gt; Use when you are not aware of the argument types or the return type is a direct mapping of the argument types.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you want to read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The bullet proof useReducer - Typescript (2/2)</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Wed, 06 Apr 2022 21:21:52 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/the-bullet-proof-usereducer-typescript-22-2kcj</link>
      <guid>https://forem.com/pffigueiredo/the-bullet-proof-usereducer-typescript-22-2kcj</guid>
      <description>&lt;p&gt;&lt;em&gt;This blog post takes by granted that you are aware of &lt;code&gt;useReducer&lt;/code&gt; logic and the basics regarding TypeScript.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing TypeScript to the table
&lt;/h2&gt;

&lt;p&gt;In the previous &lt;a href="https://dev.to/pffigueiredo/mastering-usereducer-12-5d2e"&gt;blog post&lt;/a&gt; we went in full detail on how to leverage React's &lt;code&gt;useReducer&lt;/code&gt;, but there is still something missing for it to be fully &lt;strong&gt;bullet proof&lt;/strong&gt; - TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does it help
&lt;/h3&gt;

&lt;p&gt;When applying TypeScript into &lt;code&gt;useReducer&lt;/code&gt; you will not only feel a sense of &lt;strong&gt;security&lt;/strong&gt;, but also, feel a lot more confident to touch code and modify any logic related with the states inside the &lt;code&gt;reducer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt; of using TypeScript: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type safety&lt;/li&gt;
&lt;li&gt;Type completion&lt;/li&gt;
&lt;li&gt;Makes sure all states are handled&lt;/li&gt;
&lt;li&gt;Makes sure an Action sends the correct data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt; of using TypeScript&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Brings a little more complexity&lt;/li&gt;
&lt;li&gt;Makes it harder to hack in a new state quickly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From where I see it, the &lt;strong&gt;pros&lt;/strong&gt; overcome the cons by a lot and as such, I strongly advise you to add some sort of typing to your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typing &lt;code&gt;fetchReducer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In the last post, we finished with this plain JS reducer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fcplf7fg4rjsrth1xbxri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcplf7fg4rjsrth1xbxri.png" alt="JS reducer print"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing Actions
&lt;/h3&gt;

&lt;p&gt;To start, we need to type the different possible actions, so that we have type completion depending on what we are dispatching.&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Define Action&lt;/strong&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;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Action object needs to take in &lt;strong&gt;two generics&lt;/strong&gt;, one for the Data type and one of the Error type.&lt;/p&gt;

&lt;p&gt;2- &lt;strong&gt;Define FETCH&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&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;For &lt;code&gt;FETCH&lt;/code&gt; we really only need to define the &lt;code&gt;type&lt;/code&gt;'s property type, which is a string literal and nothing more.&lt;/p&gt;

&lt;p&gt;3- &lt;strong&gt;Define RESOLVE&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataT&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When we dispatch &lt;code&gt;RESOLVE&lt;/code&gt; it means that the fetch was successful and we already have the data - this action ensures that when we do &lt;code&gt;dispatch({type: "RESOLVE"})&lt;/code&gt; there is a type error for not passing the data.&lt;/p&gt;

&lt;p&gt;4- &lt;strong&gt;Define REJECT&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&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;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;REJECT&lt;/code&gt; acts pretty much as the success action, meaning, that when we dispatch this action, TypeScript will make us pass an error along.&lt;/p&gt;

&lt;p&gt;5- &lt;strong&gt;Union of actions&lt;/strong&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;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&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;DataT&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Our action final type is just an &lt;code&gt;union&lt;/code&gt; of all our defined actions, meaning, it can take any of those forms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing States
&lt;/h3&gt;

&lt;p&gt;In order to add more strictness to our reducer, each one of the &lt;code&gt;states&lt;/code&gt; should have their own type definition. &lt;/p&gt;

&lt;p&gt;All of these states must have the same properties, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt;, but for each one of the states, these properties will have their own type definitions, depending on the situation.&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Typing &lt;code&gt;iddle&lt;/code&gt;&lt;/strong&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;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&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="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;iddle&lt;/code&gt; state takes the &lt;code&gt;DataT&lt;/code&gt; generic, so that it allows the reducer to start with initial data. Everything else is pretty standard for all the other reducer states.&lt;/p&gt;

&lt;p&gt;2- &lt;strong&gt;Typing &lt;code&gt;loading&lt;/code&gt;&lt;/strong&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;LoadingState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&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;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;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;The &lt;code&gt;loading&lt;/code&gt; state needs to take both &lt;code&gt;DataT&lt;/code&gt; and &lt;code&gt;ErrorT&lt;/code&gt; generics, as it depends too much on the implementation details if we wanna show or not errors while fetching new data.&lt;/p&gt;

&lt;p&gt;3- &lt;strong&gt;Typing &lt;code&gt;success&lt;/code&gt;&lt;/strong&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;SucessState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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;DataT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&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="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;success&lt;/code&gt; state only needs the &lt;code&gt;DataT&lt;/code&gt; generic and we can already define the &lt;code&gt;error&lt;/code&gt; property can be nothing but &lt;code&gt;null&lt;/code&gt;, this way, we protect our selves to set errors while in the &lt;code&gt;success&lt;/code&gt; state (impossible state)!&lt;/p&gt;

&lt;p&gt;4- &lt;strong&gt;Typing &lt;code&gt;failure&lt;/code&gt;&lt;/strong&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;FailureState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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;failure&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;The &lt;code&gt;failure&lt;/code&gt; state behaves pretty much like the &lt;code&gt;success&lt;/code&gt; one, but in the opposite direction, by setting the &lt;code&gt;error&lt;/code&gt; needs a value and that the &lt;code&gt;data&lt;/code&gt; must be of the &lt;code&gt;null&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;5- &lt;strong&gt;Union of States&lt;/strong&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&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;LoadingState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;SucessState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&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;FailureState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorT&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;Just like our &lt;code&gt;Action&lt;/code&gt; type, &lt;code&gt;State&lt;/code&gt; is also just an union of all the possible states that our reducer can return&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing reducer function
&lt;/h3&gt;

&lt;p&gt;Now that we have all our states and actions properly typed, it's just a matter of adding those to &lt;code&gt;fetchReducer&lt;/code&gt; function it self.&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Adding generics to the function&lt;/strong&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;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="o"&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;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;action&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;We defined &lt;code&gt;ErrorT&lt;/code&gt; as an optional generic by defining it as &lt;code&gt;string&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;2-&lt;strong&gt;Typing the arguments and the return type&lt;/strong&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;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="o"&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;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;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;We just need to take our existing &lt;code&gt;Action&lt;/code&gt; and &lt;code&gt;State&lt;/code&gt; defined types, and add them to the &lt;strong&gt;respective parameters&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;return type&lt;/strong&gt;, it was also just a matter of defining that this reducer, can only return any of the states that is inside the &lt;code&gt;State&lt;/code&gt; union type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing &lt;code&gt;useFetchReducer&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Although the &lt;code&gt;reducer&lt;/code&gt; function is already properly typed, we still need to add typing to our custom &lt;code&gt;useReducer&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Passing the generics to the &lt;code&gt;useFetchReducer&lt;/code&gt;&lt;/strong&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;// added the generics here&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useFetchReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="o"&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;span class="nx"&gt;initialData&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;

&lt;span class="c1"&gt;// removed them from the reducer&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;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;By providing generics to the &lt;code&gt;useFetchReducer&lt;/code&gt; hook, we don't need to have them on the reducer's signature anymore, as we can use the ones provided above and keep things consistent.&lt;/p&gt;

&lt;p&gt;2-&lt;strong&gt;Typing &lt;code&gt;initialData&lt;/code&gt; argument&lt;/strong&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;function&lt;/span&gt; &lt;span class="nf"&gt;useFetchReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="o"&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;span class="nx"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;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;As far as &lt;code&gt;initalData&lt;/code&gt; goes, if you wanted to pass in anything, it would have to be the same type that you defined your generic previously.&lt;/p&gt;

&lt;p&gt;3-&lt;strong&gt;Typing &lt;code&gt;initialState&lt;/code&gt; constant&lt;/strong&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;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&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="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We should use the &lt;code&gt;IddleState&lt;/code&gt; type for the &lt;code&gt;initialState&lt;/code&gt; constant, this way, if we decide to change it, TypeScript will make sure they are in sync.&lt;/p&gt;

&lt;h3&gt;
  
  
  The final type
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&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;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="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LoadingState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&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;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SucessState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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;DataT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FailureState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;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;failure&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&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;LoadingState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;SucessState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&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;FailureState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorT&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;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&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;DataT&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;useFetchReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&lt;/span&gt; &lt;span class="o"&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;span class="nx"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;:&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;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;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;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IddleState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&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="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DataT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ErrorT&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;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&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="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;failure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;data&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;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&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;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nl"&gt;default&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;state&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&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;After all this typing, we should be pretty safe when trying to access any reducer's state or even when dispatching actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dispatching Actions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftrp9rq8xkk4kl5mg0d9y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftrp9rq8xkk4kl5mg0d9y.gif" alt="dispatching actions gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can perceive from this GIF, TypeScript doesn't allow us to pass in incorrect Actions into the dispatcher function &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessing reducer's state&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.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%2Fk3neld7x4kik8yzp6jqi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fk3neld7x4kik8yzp6jqi.gif" alt="accessing state gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look closely, you will notice that TypeScript can infer what's the data and error types by the current state.&lt;/p&gt;

&lt;p&gt;This feature it's called &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html" rel="noopener noreferrer"&gt;Discriminating Unions&lt;/a&gt; and it works by having a &lt;strong&gt;Discriminator&lt;/strong&gt; property in each one of the union types, that can help TypeScript narrow down which is the current state - in our case it is the &lt;code&gt;status&lt;/code&gt;, which is unique for each of union types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By using TypeScript in conjunction with the &lt;code&gt;useReducer&lt;/code&gt; hook, you will be able to create &lt;strong&gt;robust React UI's&lt;/strong&gt;, as well as iterate on top of them with much more confidence.&lt;/p&gt;

&lt;p&gt;Summarizing everything we discussed above, these are the steps you should take to create a properly typed &lt;code&gt;useReducer&lt;/code&gt; hook:&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Type each &lt;code&gt;action&lt;/code&gt; individually&lt;/strong&gt; and create a super type, which is the union of all of them;&lt;br&gt;
2 - &lt;strong&gt;Type each &lt;code&gt;state&lt;/code&gt; individually&lt;/strong&gt; and create a super type, which is the union of all of them;&lt;br&gt;
3 - Add the necessary generic types to the &lt;code&gt;useReducer&lt;/code&gt; and &lt;code&gt;reducer&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;And that's it, you just improved your Developer Experience by a lot, and not only that, but by doing all these typing, you ended up creating a &lt;strong&gt;thin testing layer&lt;/strong&gt; that will probably spare you from many coming bugs.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; if you want read about TypeScript best practices or just web development in general!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Mastering useReducer (1/2)</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Sun, 13 Feb 2022 23:34:33 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/mastering-usereducer-12-5d2e</link>
      <guid>https://forem.com/pffigueiredo/mastering-usereducer-12-5d2e</guid>
      <description>&lt;p&gt;&lt;em&gt;This blog post takes for granted that you have some knowledge regarding React and React's Hooks.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing state in React
&lt;/h2&gt;

&lt;p&gt;As you probably know, React has 2 ways to manage state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://reactjs.org/docs/hooks-reference.html#usestate"&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer"&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are widely used across any given React application, and although they ultimately serve the same purpose (managing state), they should be used in different situations.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use &lt;code&gt;useReducer&lt;/code&gt; vs &lt;code&gt;useState&lt;/code&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;useReducer&lt;/code&gt; is usually preferable to &lt;code&gt;useState&lt;/code&gt; when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.&lt;/em&gt; - &lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer"&gt;React's  docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As stated in the paragraph above, the &lt;code&gt;useReducer&lt;/code&gt; hook should be opted in when the logic behind your state is a bit more complex or depends on the previous state.&lt;/p&gt;

&lt;p&gt;✅ Good use cases for &lt;code&gt;useReducer&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changing 1 piece of state also changes others (co-related state values);&lt;/li&gt;
&lt;li&gt;The state is complex and has a lot of moving parts;&lt;/li&gt;
&lt;li&gt;When you want/need more predictable state transitions;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;useReducer&lt;/code&gt; hook
&lt;/h2&gt;

&lt;p&gt;Now that we have some context on where to use this hook, it's time to take a closer look at it's API. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useReducer&lt;/code&gt; it's a built in function brought by React that has 2 different signatures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useReducer(reducer, initialArg);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useReducer(reducer, initialArg, init);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;useReducer&lt;/code&gt; arguments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;reducer&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reducer&lt;/code&gt; as it's own name indicates, it's a function that takes some information and &lt;strong&gt;reduces&lt;/strong&gt; it into something, and this is the place where the "magic" happens.&lt;/p&gt;

&lt;p&gt;It takes two arguments, the current &lt;code&gt;state&lt;/code&gt; and the &lt;code&gt;action&lt;/code&gt; which is dispatched by the UI. By taking a given action type, a reducer will return the next piece of state, usually by deriving the previous state.&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;function&lt;/span&gt; &lt;span class="nf"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="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;&lt;strong&gt;&lt;code&gt;initialState&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This argument is pretty self explanatory, it's just the state that the &lt;code&gt;useReducer&lt;/code&gt; hook will start with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;init&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;init&lt;/code&gt; is a function that allows you do some logic around the initial state, as it will take the value you passed as &lt;code&gt;initialState&lt;/code&gt; and return a "new" &lt;code&gt;initialState&lt;/code&gt; based on 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;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialCount&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;useReducer&lt;/code&gt; returned values
&lt;/h3&gt;

&lt;p&gt;Very similar to &lt;code&gt;useState&lt;/code&gt;, this hook returns an array with two values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first, to show the current state;&lt;/li&gt;
&lt;li&gt;The second, a way to change the state, and create a re-render in the application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;state&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This value doesn't need much explanation, it is simply the current state returned by the &lt;code&gt;useReducer&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;dispatch&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a function where you can pass the the possible &lt;code&gt;actions&lt;/code&gt; that you define for your &lt;code&gt;reducer&lt;/code&gt; to handle. Taking the previous &lt;code&gt;counterReducer&lt;/code&gt; by example, these could look like this:&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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;-&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;h2&gt;
  
  
  Managing the fetching logic with the &lt;code&gt;useReducer&lt;/code&gt; hook
&lt;/h2&gt;

&lt;p&gt;Now that we have a better understanding of what the &lt;code&gt;useReducer&lt;/code&gt; hook can do for us, it's time to get our hands dirty and make usage of this React hook to handle any given &lt;strong&gt;fetching related state&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching state
&lt;/h3&gt;

&lt;p&gt;In order to use &lt;code&gt;useReducer&lt;/code&gt;, you must first think what will be the state that you want to manage, these are usually all the things that you might have in a bunch of &lt;code&gt;useState&lt;/code&gt; hooks, like &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;errorMessage&lt;/code&gt;, &lt;code&gt;fetchState&lt;/code&gt;, etc...&lt;/p&gt;

&lt;p&gt;In this scenario, as we want to create a hook that will allow us to manage fetching logic. And as far as fetch logic goes, all the pieces you need are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;state&lt;/strong&gt;: to know if the application is &lt;code&gt;iddle&lt;/code&gt;, &lt;code&gt;loading&lt;/code&gt;, if the fetch was a &lt;code&gt;success&lt;/code&gt; or a &lt;code&gt;failure&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;error&lt;/strong&gt;: a error message in case something went wrong&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data&lt;/strong&gt; : the response data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so, now that we have our &lt;code&gt;state&lt;/code&gt; structure defined, we can setup our &lt;code&gt;initialState&lt;/code&gt;.&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;// "iddle" state because we haven't fetch anything yet!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&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="na"&gt;data&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;error&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fetching reducer
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Actions
&lt;/h4&gt;

&lt;p&gt;The second step, is to create the logic that will lead to different app states. That logic lives under the &lt;code&gt;reducer&lt;/code&gt; function and for us to mount that logic, we should start by thinking on the "actions" that we need to perform.&lt;/p&gt;

&lt;p&gt;For the fetching logic, we will need the following actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FETCH&lt;/strong&gt;: action to be called when the request starts;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RESOLVE&lt;/strong&gt;: action to be called if the response is successful;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REJECT&lt;/strong&gt;: action to be called if the requests throws an error or the response is "invalid";&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Bear in mind that you can call these actions whatever you want, as long as they reflect what's being done and it makes sense for you.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  State transitions
&lt;/h4&gt;

&lt;p&gt;Each of these actions (&lt;code&gt;FETCH&lt;/code&gt;, &lt;code&gt;RESOLVE&lt;/code&gt; and &lt;code&gt;REJECT&lt;/code&gt;) will lead to a state transition, thus, producing a new output (a new state). &lt;/p&gt;

&lt;p&gt;So now, it's just a matter of figuring out which will be the state that each of these actions will output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;FETCH&lt;/code&gt;&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqmuvm34vzliyutazzrc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqmuvm34vzliyutazzrc.jpg" alt="FETCH state transition" width="322" height="316"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;RESOLVE&lt;/code&gt;&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj8nhd7oml0vnyincksm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj8nhd7oml0vnyincksm.png" alt="RESOLVE state transition" width="289" height="316"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;REJECT&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqv8m2wim5tjnrjqgbu19.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqv8m2wim5tjnrjqgbu19.jpg" alt="REJECT state transition" width="289" height="316"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h4&gt;
  
  
  Implementing &lt;code&gt;useReducer&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;With all the pseudo-code and decisions we have made above, we are now able to take advantage of &lt;code&gt;useReducer&lt;/code&gt; to manage the fetching 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;initialState&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="na"&gt;data&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;error&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;currentState&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;data&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;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;failure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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;span class="nl"&gt;default&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;currentState&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Fetching data
&lt;/h3&gt;

&lt;p&gt;The implementation code is done, let's now check how would the code look look if we were fetching some data through our &lt;code&gt;useReducer&lt;/code&gt;.&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;function&lt;/span&gt; &lt;span class="nf"&gt;fetchIt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Start fetching!&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&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://www.reddit.com/r/padel.json&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&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;response&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="nf"&gt;then&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// We got our data!&lt;/span&gt;
            &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&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="p"&gt;})&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;error&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;// We got an error!&lt;/span&gt;
        &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&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;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&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="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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt; : undefined&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&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="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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt; : undefined&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt; : undefined&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&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="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="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetchIt&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;Fetch&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating &lt;code&gt;useFetchReducer&lt;/code&gt; custom hook
&lt;/h2&gt;

&lt;p&gt;Now, you will probably want to use this very same code to control your application's state in every place where you are performing an HTTP request. &lt;/p&gt;

&lt;p&gt;Luckily for us, React brings a huge &lt;a href="https://reactjs.org/docs/composition-vs-inheritance.html"&gt;composition&lt;/a&gt; power packed in, making our life's quite simple when creating custom hooks through other existing React hooks (&lt;code&gt;useReducer&lt;/code&gt; in this case).&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting &lt;code&gt;useReducer&lt;/code&gt; hook
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;1st step&lt;/strong&gt;, is to create a new file named &lt;code&gt;use-fetch-reducer.js&lt;/code&gt; or whatever you wanna call it, as long and it starts with &lt;strong&gt;use&lt;/strong&gt; (to be identified as an hook).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;2nd step&lt;/strong&gt;, is to take (copy) all the code that we implemented before, and paste it inside an exported function with the name &lt;code&gt;useFetchReducer&lt;/code&gt;. It should look something like this:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useFetchReducer&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;initialState&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="na"&gt;data&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;error&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;currentState&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESOLVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;REJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;data&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;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;failure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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;span class="nl"&gt;default&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;currentState&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&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;The &lt;strong&gt;3rd step&lt;/strong&gt; is to take out our &lt;code&gt;useReducer&lt;/code&gt; result and return it instead, so that we can use &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;dispatch&lt;/code&gt; in every other component:&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;//...&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To wrap things up, we should make this hook as "generic" as possible, so that it can satisfy the need of every component where it's being called from. In order to get there, the &lt;strong&gt;4th step&lt;/strong&gt; passes by providing a way for consumers to set the &lt;code&gt;initialData&lt;/code&gt; themselves, because it might not always start as &lt;code&gt;null&lt;/code&gt;:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useFetchReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialData&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;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&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="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using &lt;code&gt;useFetchReducer&lt;/code&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Import the newly created hook into your component;&lt;/li&gt;
&lt;li&gt;Execute it as &lt;code&gt;const [state, dispatch] = useFetchReducer();&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use it's &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;dispatch&lt;/code&gt; as you would for the &lt;code&gt;useReducer&lt;/code&gt; hook.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/elastic-framework-9wqd9"&gt;Running Code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2qmb1k77g6bfv2981vr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2qmb1k77g6bfv2981vr.gif" alt="useFetchReducer" width="1256" height="890"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If your app state is becoming somewhat complex and the number of &lt;code&gt;useState&lt;/code&gt; is mounting up, it might be time to do a small switch and take advantage of &lt;code&gt;useReducer&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;If you have decided to use &lt;code&gt;useReducer&lt;/code&gt;, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Think of the &lt;strong&gt;State&lt;/strong&gt; you want to manage;&lt;/li&gt;
&lt;li&gt;Think of the &lt;strong&gt;Actions&lt;/strong&gt; that that will trigger state transitions;&lt;/li&gt;
&lt;li&gt;Think for the &lt;strong&gt;State Transitions&lt;/strong&gt; that will happen when calling the defined set of states.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these thought out, it's time to write your own reducer and call the &lt;code&gt;useReducer&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;If the logic you just created can be reused across your application, create a custom hook and enjoy 😉&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The 2nd part of this series will bring some &lt;strong&gt;type safety&lt;/strong&gt; to the table, make sure to follow me on &lt;a href="https://twitter.com/P_FFigueiredo"&gt;twitter&lt;/a&gt; if you don't want to miss it!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. the &lt;code&gt;useFetchReducer&lt;/code&gt; code was highly inspired into &lt;a href="https://dev.to/davidkpiano"&gt;David K. Piano&lt;/a&gt;'s code, present in this great &lt;a href="https://dev.to/davidkpiano/no-disabling-a-button-is-not-app-logic-598i"&gt;blog post&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
_&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TypeScript Utility: keyof nested object</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Wed, 15 Dec 2021 23:37:56 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/typescript-utility-keyof-nested-object-2pa3</link>
      <guid>https://forem.com/pffigueiredo/typescript-utility-keyof-nested-object-2pa3</guid>
      <description>&lt;p&gt;&lt;em&gt;In this blog post, we will learn how to build a TypeScript util type, that exposes all the key paths of an object, including the nested ones.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is that useful?
&lt;/h2&gt;

&lt;p&gt;Have you ever built TypeScript function that receives a specific property of an object, by specifying the object and the path to that object's property? Something like this:&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;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rex&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&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;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &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;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&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="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dog.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Rex&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Well, obviously this works very well, but you aren't taking full advantage of TypeScript! You can easily do a typo on the second argument (path) and lose some precious type with debugging this.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can TypeScript help us then?
&lt;/h2&gt;

&lt;p&gt;Unfortunately for us, there isn't yet a native utility type that can provide us all the key paths inside a nested object. But if your object only has 1 level of deepness, TypeScript's &lt;code&gt;keyof&lt;/code&gt; operator will serve just fine!&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;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Programmer&lt;/span&gt;&lt;span class="dl"&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;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&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;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
 &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This way, you will have a real type safe function, that will only allow you to add &lt;code&gt;"name"&lt;/code&gt;, &lt;code&gt;"age"&lt;/code&gt; or &lt;code&gt;"job"&lt;/code&gt; as the second argument.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fspcg5iqs6k4p9zkm7wsh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fspcg5iqs6k4p9zkm7wsh.gif" alt="keyof example gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you didn't understand some of technicalities I showed above, stay with me, as I will explain in more detail bellow.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Objects with more than 1 level deepness
&lt;/h3&gt;

&lt;p&gt;Now, for the objects with more than 1 level of deepness, &lt;code&gt;keyof&lt;/code&gt; isn't nearly enough as you may have realized by now.&lt;/p&gt;

&lt;p&gt;Before entering in TypeScript's implementation details, let's try to think of an algorithm that would allow us to get all the keys of an object with N levels of deepness.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go through the object's keys&lt;/li&gt;
&lt;li&gt;If the key's value is not an object , then it's a valid key&lt;/li&gt;
&lt;li&gt;Else, if the key is an object, concat this key and go back to step 1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this algorithm, and these "simple" programming principles, a loop statement, a conditional and recursiveness, this doesn't seem so hard after all!&lt;/p&gt;

&lt;p&gt;Now, let's take that algorithm and build a JS function that could extract all the keys of all the nodes in any given object.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pfigueiredo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pfigueiredo&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getObjectKeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;previousPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Step 1- Go through all the keys of the object&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&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;// Get the current path and concat the previous path if necessary&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;previousPath&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;previousPath&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;key&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;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Step 2- If the value is a string, then add it to the keys array&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&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;objectKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;objectKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Step 3- If the value is an object, then recursively call the function&lt;/span&gt;
            &lt;span class="nf"&gt;getObjectKeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;currentPath&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getObjectKeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [ 'name', 'age', 'dog', 'dog.owner', 'dog.owner.name' ]&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;So, we know how to do this programmatically, the goal now, is to try and apply the same kind of concepts with TypeScript existing operators and utility types to build a &lt;code&gt;generic type&lt;/code&gt; that will give us all the keys of an object as literal types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the TypeScript utility type
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The utility type we will create bellow, is &lt;strong&gt;only possible since TypeScript 4.0&lt;/strong&gt; version was released, as it introduced literal types.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this section, we will go step by step, on how to create a TypeScript's utility type that is capable of extract all keys inside any given object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type definition
&lt;/h3&gt;

&lt;p&gt;The first step to create this utility, is obviously declaring a new TypeScript type and give it a name:&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Declaring a new type&lt;/strong&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;NestedKeyOf&lt;/span&gt; &lt;span class="o"&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 next step, is to make this type be "generic", meaning, it should accept any given object that we pass into it.&lt;br&gt;
TypeScript already has this &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;generic&lt;/a&gt; feature embedded, and it allows us to create a flexible util that can accept any given object. &lt;/p&gt;

&lt;p&gt;2- &lt;strong&gt;Accept a generic type parameter&lt;/strong&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;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;// using&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ObjectKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Person&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;Adding a generic type parameter by itself doesn't restraint the type you can pass into the utility. For that, we need to add the &lt;code&gt;extends&lt;/code&gt; keyword, in order to only accept object types - any type that follows the "key-value" pair data type.&lt;/p&gt;

&lt;p&gt;3- &lt;strong&gt;Constraint the generic parameter&lt;/strong&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;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Great, we have a defined the type's signature, now we need to do the "real work", that is, making the implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type implementation
&lt;/h3&gt;

&lt;p&gt;Going back to our algorithm, the first step to create this utility is "Go through the object's keys". TypeScript makes this easy for us with something called &lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html" rel="noopener noreferrer"&gt;Mapped Types&lt;/a&gt;, which is a way to go through an object's keys and set the value's type based on each one of the keys.&lt;/p&gt;

&lt;p&gt;1- &lt;strong&gt;Going through the object's keys&lt;/strong&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;// Create an object type from `ObjectType`, where the keys&lt;/span&gt;
&lt;span class="c1"&gt;// represent the keys of the `ObjectType` and the values &lt;/span&gt;
&lt;span class="c1"&gt;// represent the values of the `ObjectType`&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now that we were able to go through all the object's keys and use them to access each one of the object's values, we can move on to the 2nd step of the algorithm: "If the key's value is not an object , then it's a valid key". &lt;/p&gt;

&lt;p&gt;We are going to do that check by making usage of TypeScript's &lt;a href="https://www.typescriptlang.org/docs/handbook/2/conditional-types.html" rel="noopener noreferrer"&gt;Conditional Types&lt;/a&gt;, which work as following:&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;// Take a `Type`, check if it "extends" `AnotherType` &lt;/span&gt;
&lt;span class="c1"&gt;// and return a type based on that&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Animal&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="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;2- &lt;strong&gt;Checking if it's a valid key&lt;/strong&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;// If the value is NOT of type `object` then &lt;/span&gt;
&lt;span class="c1"&gt;// set it as the generated object's value type&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; 
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="cm"&gt;/*TODO*/&lt;/span&gt; 
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Key&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// But we want what's under the object's values, &lt;/span&gt;
&lt;span class="c1"&gt;// so we need to access it&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&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;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pfigueiredo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pfigueiredo&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;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Person&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;// "name" | "age" | ""&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;So, we now have access to all the object's first level keys, but we are obviously still missing the path to the other level's properties, such as &lt;code&gt;dog.owner&lt;/code&gt; and &lt;code&gt;dog.owner.name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to achieve that, we should follow the 3rd step of our algorithm:  "Else, if the key is an object, concat this key and go back to step 1." &lt;/p&gt;

&lt;p&gt;To achieve that, we need to make usage of TypeScript's &lt;strong&gt;recursive types&lt;/strong&gt;, which work as any other programming language really - having a condition that calls the same "type" that invoked the condition (recursiveness), and having a condition that leads to an actual result.&lt;/p&gt;

&lt;p&gt;3 - &lt;strong&gt;Add type recursiveness&lt;/strong&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;// 1 - If it's an object, call the type again&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; 
&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&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;Key&lt;/span&gt;
&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// 2 - Concat the previous key to the path&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;Key&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;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&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="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Key&lt;/span&gt;
&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// 3 - Add the object's key&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;Key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;Key&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;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&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="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Key&lt;/span&gt;
&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That is basically it, this &lt;code&gt;NestedKeyOf&lt;/code&gt; utility type should already be capable of extracting all the possible property paths of an object with any given depth, but TypeScript will probably still be yelling at you for using non-strings/numbers inside the literals, let's fix that!&lt;/p&gt;

&lt;p&gt;In order to only select keys of a specific type, we need to leverage the &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html" rel="noopener noreferrer"&gt;Intersection Types&lt;/a&gt;, which is just a matter of using the &lt;code&gt;&amp;amp;&lt;/code&gt; operator. &lt;/p&gt;

&lt;p&gt;4- &lt;strong&gt;Extracting string/number keys only&lt;/strong&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;// add `&amp;amp; (string | number)` to the keyof ObjectType&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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="nx"&gt;Key&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;ObjectType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;Key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;Key&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;NestedKeyOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&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="s2"&gt;`&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;Key&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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  SortBy sample with NestedKeyOf
&lt;/h3&gt;

&lt;p&gt;Now that we have finalised the implementation of our TypeScript utility type, it's time to see a simple sample where it would be super useful in any project you might be working in 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fm3ng3odgbz8rhetor7b1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fm3ng3odgbz8rhetor7b1.gif" alt="sortBy function gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By using this utility in the &lt;code&gt;sortBy&lt;/code&gt; function, we are able to safely select one of the object's properties and make sure we don't do any typo and keep in sync with the object's structure and what we are passing at all times 🤯&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Create a type that accepts a &lt;strong&gt;generic&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraint the generic&lt;/strong&gt; to be an object&lt;/li&gt;
&lt;li&gt;Create a new object with the help of &lt;strong&gt;Mapped Types&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;For each key, check if the value is an object or a primitive type&lt;/li&gt;
&lt;li&gt;If it's an object then concat the current key and call the type in a &lt;strong&gt;recursiveness manner&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Only look for &lt;strong&gt;string and number keys&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;As a side note, I wanna appreciate the fantastic &lt;a href="https://twitter.com/DavidSherret" rel="noopener noreferrer"&gt;David Sherret&lt;/a&gt;, which posted a &lt;a href="https://stackoverflow.com/questions/65332597/typescript-is-there-a-recursive-keyof/65333050#65333050" rel="noopener noreferrer"&gt;stack overflow answer&lt;/a&gt; that looked somewhat like the utility type I described above 🙏&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Cheat Sheet for CSS units</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Thu, 11 Nov 2021 10:55:34 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/a-cheat-sheet-for-size-units-4cbi</link>
      <guid>https://forem.com/pffigueiredo/a-cheat-sheet-for-size-units-4cbi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is an opinionated take on when to use each CSS unit, feel free and encouraged to disagree and make an argument on that, if that's the case.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;REM&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;font-size&lt;/li&gt;
&lt;li&gt;spacing&lt;/li&gt;
&lt;li&gt;border-radius&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;EM&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;letter-spacing&lt;/li&gt;
&lt;li&gt;media-queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;PX&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;border-width&lt;/li&gt;
&lt;li&gt;shadows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other Units&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;z-index (integer)&lt;/li&gt;
&lt;li&gt;line-height (integer)&lt;/li&gt;
&lt;li&gt;sizes (%)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CSS units
&lt;/h2&gt;

&lt;p&gt;Have you ever wondered what CSS units to use on any specific case? If so, this cheat sheet will be definitely useful for you! &lt;/p&gt;

&lt;p&gt;There are &lt;code&gt;em&lt;/code&gt;, &lt;code&gt;rem&lt;/code&gt;, &lt;code&gt;px&lt;/code&gt; and many other units out there, and we always want to apply what's described as a "best practice". That's why I came up with this cheat sheet, this is something I look up for whenever I need to come up with a new &lt;code&gt;theme&lt;/code&gt; or new &lt;code&gt;design tokens&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Design tokens are all the values needed to construct and maintain a design system — spacing, color, typography, object styles, animation, etc. - by &lt;a href="https://spectrum.adobe.com/page/design-tokens/"&gt;Adobe&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  REM
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rem&lt;/code&gt; is a relative CSS unit that scales with the root element's font size. Meaning, that it uses the  font-size that defined under the &lt;code&gt;html&lt;/code&gt; tag to be calculated.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why is this unit useful?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main purpose of &lt;code&gt;rem&lt;/code&gt; units, is related with its scaling with the document's font-size, meaning that if a user &lt;strong&gt;updates the font-size on the browser settings&lt;/strong&gt; (yes, that's a thing), and if the typography is defined with &lt;code&gt;rem&lt;/code&gt; units, everything will scale as it is meant to!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In which scenarios should I be using &lt;code&gt;rem&lt;/code&gt; then?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could think of this, as "whenever I want things to scale, based on the font-size". In the end, these are the &lt;code&gt;design tokens&lt;/code&gt; where you should be using this unit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Font-size&lt;/strong&gt; - So that font-size scales with the defined font-size settings by the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spacing&lt;/strong&gt; - Inside this &lt;code&gt;design token&lt;/code&gt;, lives all the CSS properties that add any sense of spacing between elements, like &lt;code&gt;margin&lt;/code&gt; or &lt;code&gt;padding&lt;/code&gt;. And for these, I find it useful to have it scaling with the root's font-size, so that the same visual and hierarchy effect is shown to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Border-radius&lt;/strong&gt; - This unit makes most sense to be in &lt;code&gt;rem&lt;/code&gt; because the "box" elements that have it defined, are usually wrapping content that is also defined in &lt;code&gt;rem&lt;/code&gt;, making it then convenient to have this "rounded" effect scaling with font-size also.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  EM
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;em&lt;/code&gt; is a relative CSS unit that scales with the parent element's font-size. Meaning that if an element has a font-size of &lt;code&gt;2em&lt;/code&gt;, it will be the double of it's parent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why is this unit useful?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;em&lt;/code&gt; units are useful when you want to have something to scale depending on the currently defined font-size. Icons are good example of this, most times you will want your icons size to be relative to whatever is the font-size defined on the context they are placed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In which scenarios should I be using &lt;code&gt;em&lt;/code&gt; then?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There aren't many scenarios in which this unit is useful, it's mostly when you want properties to scale depending on the context's font-size.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Letter-Spacing&lt;/strong&gt; - &lt;code&gt;letter-spacing&lt;/code&gt; as the name indicates, is correlated with the letters them selves, and as such it should scale with whatever is the defined font-size for this parent's element.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Media Queries&lt;/strong&gt; - For multiple reasons that I won't enter in detail, &lt;code&gt;em&lt;/code&gt; is the most consistent unit when it comes to media queries and works pretty well across all browsers. You can read more about this topic in this thorough &lt;a href="https://zellwk.com/blog/media-query-units/"&gt;blog post&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  PX
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;px&lt;/code&gt; has been the most commonly used CSS unit when it comes to web development. It is an absolute unit, and &lt;code&gt;1px&lt;/code&gt; represents 1/96th of 1 inche.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Why is this unit useful?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;px&lt;/code&gt; units are useful when you want to have something to be static and not change depending on factor's like the defined font-size.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In which scenarios should I be using &lt;code&gt;px&lt;/code&gt; then?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This unit is the clear winner when it comes "let's build this fast and not put much thinking into it". But in fact, there aren't that many useful scenarios in which you should be using this unit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Border-width&lt;/strong&gt; - As far as borders goes, you usually just want them to add some kinda of emphasis or to separate contexts, so you really don't need them to scale depending on anything.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shadows&lt;/strong&gt; - We usually use shadows to give a sense of elevation or to create some type of stacking, and that's another thing where we don't need things to scale.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Other units
&lt;/h2&gt;

&lt;p&gt;For the particular use case of defining values for &lt;code&gt;design tokens&lt;/code&gt; like &lt;code&gt;z-index&lt;/code&gt;, &lt;code&gt;line-heights&lt;/code&gt; or &lt;code&gt;sizes&lt;/code&gt;, I tend to not use any of the units above, and use the following "miscellaneous" instead:&lt;/p&gt;

&lt;h3&gt;
  
  
  Integer number
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Z-index&lt;/strong&gt; - For this CSS property, your only shot it so use an integer number, so there isn't much to say in that regard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line-height&lt;/strong&gt; - Line-height's value depends on the defined font-size to set it's value, similar to how the &lt;code&gt;em&lt;/code&gt;  unit works. But there is no need to specify any CSS unit, as specifying an integer number like &lt;code&gt;line-height: 2;&lt;/code&gt; will lead to a line-height value, that is the double of the font-size.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  % value
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;sizes&lt;/strong&gt; - This design token includes &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;, and having pre-defined % values like &lt;code&gt;width: 50%&lt;/code&gt; or &lt;code&gt;height: 75%&lt;/code&gt;, is usually what I tend to find the most useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In today's web development using &lt;code&gt;px&lt;/code&gt; as a CSS unit for every other property isn't really a choice if you wanna makes thing right by your users.&lt;/p&gt;

&lt;p&gt;Users should have the &lt;strong&gt;option to update their browser settings&lt;/strong&gt; and still have a pretty good experience on your website, with that in mind, make sure you are using &lt;strong&gt;the appropriate CSS units&lt;/strong&gt; for each property, and deliver an awesome experience!&lt;/p&gt;

</description>
      <category>react</category>
      <category>css</category>
      <category>javascript</category>
      <category>design</category>
    </item>
    <item>
      <title>Jest testing without the noise</title>
      <dc:creator>Pedro Figueiredo</dc:creator>
      <pubDate>Wed, 03 Nov 2021 23:22:38 +0000</pubDate>
      <link>https://forem.com/pffigueiredo/jest-testing-without-the-noise-2n8g</link>
      <guid>https://forem.com/pffigueiredo/jest-testing-without-the-noise-2n8g</guid>
      <description>&lt;p&gt;&lt;em&gt;This post takes by granted that you already have Jest set up and a test script defined on your &lt;code&gt;package.json&lt;/code&gt; file.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running 1 test file at a time
&lt;/h2&gt;

&lt;p&gt;You know that feeling when you you are writing &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; tests and for you to check their correctness, you need to run all of them, and on top of that, &lt;strong&gt;wait a couple minutes&lt;/strong&gt;? ⌛&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Well I at least did for a while.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But luckily, there is a better way! By running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm test -- FILE_NAME
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the command above, we will only be running the &lt;strong&gt;test suites inside that file&lt;/strong&gt;! Not only that, but you don't even need to write the full name of the file, as Jest will be running against every file whose name matches the FILE_NAME's regex expression.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use the command
&lt;/h3&gt;

&lt;p&gt;Looking at the folder structure bellow 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  /components   
    /button      
      Button.tsx
      Button.test.tsx
      ButtonCTA.test.tsx
    /heading
      Heading.tsx
      Heading.test.tsx
    /...
package.json
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If would run &lt;code&gt;npm run test -- button&lt;/code&gt; you would actually be running the tests inside both &lt;code&gt;Button.test.tsx&lt;/code&gt; and &lt;code&gt;ButtonCTA.test.tsx&lt;/code&gt;. That is because Jest will run all the tests whose name match the following regex &lt;code&gt;/button/i&lt;/code&gt;, making it look not only for all the file names that include the string &lt;code&gt;button&lt;/code&gt;, but also ignoring the casing.&lt;/p&gt;

&lt;p&gt;So, in this scenario, to only run the tests inside &lt;code&gt;Button.test.tsx&lt;/code&gt; you should actually be typing something more restrictive like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm test -- button.test
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9m0hgt6wjr7wvhcxla6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9m0hgt6wjr7wvhcxla6.png" alt="Test passing inside Button.test.tsx" width="667" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running 1 test case or 1 test suite
&lt;/h2&gt;

&lt;p&gt;Now, many times we really &lt;strong&gt;just want to run that one test&lt;/strong&gt; that is being "stubborn" and doesn't want to pass, at all.&lt;/p&gt;

&lt;p&gt;We already know how to strict Jest to only run tests inside one file, but that can still take some time, depending on how many tests we have in that file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1 - Run by test name
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://jestjs.io/docs/setup-teardown#general-advice"&gt;Jest Docs&lt;/a&gt;, it is possible to only run 1 test by name, with the following comand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;npm test -- -t '&amp;lt;testName&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;OR &amp;lt;testSuiteName&amp;gt;&lt;span class="s1"&gt;'     
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But by doing so, you will not only have some probabilities of running more than 1 test (because name collapses), as well, as &lt;strong&gt;it will still be kinda unoptimized&lt;/strong&gt;, since Jest must look into all the files, to check if there is any name match, thus, passing or running the tests.&lt;/p&gt;

&lt;p&gt;Now, if we concat both flags of &lt;strong&gt;looking for the file name&lt;/strong&gt; + the one to &lt;strong&gt;look for the test name&lt;/strong&gt;, we could create something nice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm run test -- button.test -t "should render the primary button"   
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command above, will only run the tests inside &lt;code&gt;button.test.tsx&lt;/code&gt; whose name matches "should render the primary button". This way we can run a more optimized way to run the specific test we want!&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2 - Using &lt;code&gt;.only()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When marking a test case/suite with &lt;code&gt;.only&lt;/code&gt;, Jest will only run that one (you can actually mark more than one), skipping  all the others.&lt;/p&gt;

&lt;p&gt;This way, we can combine the command we learned before to run only 1 file (&lt;code&gt;npm test -- button.test&lt;/code&gt;) and do following on top of 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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Button&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Only this test will be executed inside this file&lt;/span&gt;
  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render the primary button&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="p"&gt;{...(&lt;/span&gt;&lt;span class="nx"&gt;Primary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Genie/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should render the secondary button&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Secondary&lt;/span&gt; &lt;span class="p"&gt;{...(&lt;/span&gt;&lt;span class="nx"&gt;Secondary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Genie/i&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;That way, every time we run the tests pointing into the &lt;code&gt;button.test.tsx&lt;/code&gt; file, only the test marked with &lt;code&gt;.only&lt;/code&gt; will be executed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 3 - Watch mode
&lt;/h3&gt;

&lt;p&gt;Watch mode, as the name indicates, sets up a running environment that is watching for changes inside our test files.&lt;/p&gt;

&lt;p&gt;Fortunately, watch mode brings a &lt;strong&gt;wizard menu&lt;/strong&gt;, that allows us to easily filter whatever file or test we want to be watching the changes, making it way faster to execute the test!&lt;/p&gt;

&lt;p&gt;The first step is obviously to start the watch mode with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm run test -- --watch
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And once the menu appears, you should start by choosing the file in which the test you want to run stands - &lt;strong&gt;simply press "p"&lt;/strong&gt; and start typing out the name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn89agshj78o0krjh078b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn89agshj78o0krjh078b.png" alt="Jest menu showing all the possible options" width="573" height="135"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now that only 1 file's tests are being run, it's time to select the test we are interested in! And for that, you should just &lt;strong&gt;press "t" in the terminal&lt;/strong&gt; and once again, choose the test by typing his name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92yxvd5zjfumf243zwbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92yxvd5zjfumf243zwbj.png" alt="Jest menu showing how to choose test names" width="562" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And magic happens 🎩! Now every time you make changes to that specific test and save the file, only that test will be executed, how cool is that!? &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Whenever you are trying to fix that one test, stop being lazy by just running the command you have set up on your &lt;code&gt;package.json&lt;/code&gt; file and &lt;strong&gt;use one of the techniques listed above&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;It will not only save you some time, but also improve the &lt;strong&gt;overall Developer Experience&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>testing</category>
      <category>react</category>
    </item>
  </channel>
</rss>
