<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: kimuson</title>
    <description>The latest articles on DEV Community by kimuson (@kimuson).</description>
    <link>https://dev.to/kimuson</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%2F638843%2F5d03b1d4-3148-4301-92e4-09e96da66b3f.png</url>
      <title>DEV Community: kimuson</title>
      <link>https://dev.to/kimuson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kimuson"/>
    <language>en</language>
    <item>
      <title>Introducing Claude Crew: Enhancing Claude Desktop's Coding Agent Capabilities</title>
      <dc:creator>kimuson</dc:creator>
      <pubDate>Thu, 03 Apr 2025 09:14:13 +0000</pubDate>
      <link>https://dev.to/kimuson/introducing-claude-crew-enhancing-claude-desktops-coding-agent-capabilities-36ah</link>
      <guid>https://dev.to/kimuson/introducing-claude-crew-enhancing-claude-desktops-coding-agent-capabilities-36ah</guid>
      <description>&lt;p&gt;I've developed a tool called "Claude Crew" that extends Claude Desktop's capabilities as an autonomous coding agent. I'd like to introduce this tool and share some insights gained during its development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/claude-crew" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/claude-crew&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Crew is designed with inspiration from OpenHands but specifically for Claude Desktop. It leverages Model Context Protocol (MCP) and custom instructions to maximize Claude Desktop's coding capabilities.&lt;/p&gt;

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

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

&lt;ul&gt;
&lt;li&gt;Created Claude Crew, an autonomous coding agent for Claude Desktop similar to OpenHands&lt;/li&gt;
&lt;li&gt;Provides RAG functionality and project-optimized MCP to enhance Claude's performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a Claude Desktop-Based Agent?
&lt;/h2&gt;

&lt;p&gt;Recently, LLM-based coding tools have become widespread, with solutions like Cline, Cursor, Devin, and others being actively used by developers. You may have tried some of these or even incorporated them into your workflow.&lt;/p&gt;

&lt;p&gt;Claude Desktop comes equipped with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom instructions setting capabilities&lt;/li&gt;
&lt;li&gt;A Model Context Protocol (MCP) client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By configuring MCP with file operations (through the official filesystem implementation) and third-party or self-built shell access, and setting custom instructions to enable agent behavior, Claude Desktop can function as a coding agent on its own.&lt;/p&gt;

&lt;p&gt;While these existing mechanisms make it possible to create a coding agent based on Claude Desktop, basic MCP integration alone has limitations when it comes to understanding context in large projects and efficiently using tokens. Claude Crew provides a toolset to address these challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Differences from Editor-Integrated Coding Assistants
&lt;/h2&gt;

&lt;p&gt;AI coding assistants like Cline, Cursor, and Windsurf are designed for human collaboration. They follow an interactive workflow where humans review and help modify code in real-time while the agent is making edits.&lt;/p&gt;

&lt;p&gt;In contrast, Claude Crew aims for a more autonomous workflow based on the concept of "create XXX" tasks, where AI completes tasks autonomously from start to finish.&lt;/p&gt;

&lt;p&gt;In essence, Claude Crew resembles implementing OpenHands on Claude Desktop.&lt;/p&gt;

&lt;p&gt;It's worth noting that higher autonomy isn't always better—collaborative and autonomous approaches have clear trade-offs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Collaborative (Cline/Cursor)&lt;/th&gt;
&lt;th&gt;Autonomous (Claude Crew)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Better at difficult or poorly articulated problems&lt;/td&gt;
&lt;td&gt;Only handles well-defined, simpler tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human judgment can redirect to solve harder problems&lt;/td&gt;
&lt;td&gt;Removes human bottlenecks for parallel processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires continuous feedback&lt;/td&gt;
&lt;td&gt;Only needs final result verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires engineering feedback&lt;/td&gt;
&lt;td&gt;Works better with feedback from non-technical stakeholders&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In practice, both approaches complement each other.&lt;/p&gt;

&lt;p&gt;In my own workflow, once Claude Crew became usable, I would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delegate simpler feature implementations to Claude Crew in parallel&lt;/li&gt;
&lt;li&gt;Focus my attention on more complex problems using Cursor&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Problems Claude Crew Solves
&lt;/h2&gt;

&lt;p&gt;While basic agent functionality can be achieved by simply connecting Claude Desktop with MCP, there were several challenges to overcome for practical use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context Understanding Limitations&lt;/strong&gt; - Understanding related code in large projects is crucial but difficult&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Restrictions&lt;/strong&gt; - Claude Desktop offers unlimited usage with a subscription, but has relatively strict character limits, requiring efficient context window usage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature Gaps&lt;/strong&gt; - Compared to editor-integrated tools like Cursor, Claude Desktop lacks feedback mechanisms for LLMs, which would require significant implementation work to match&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Claude Crew addresses these challenges comprehensively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builds local RAG for your codebase to effectively supplement context understanding&lt;/li&gt;
&lt;li&gt;Provides effective LLM feedback reflecting your development project information

&lt;ul&gt;
&lt;li&gt;Automatic unit testing and static analysis when files are modified, with results fed back to minimize trial and error and produce correct code&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Offers an all-in-one solution with features that enhance coding performance but would be difficult to set up individually:

&lt;ul&gt;
&lt;li&gt;Memory banks, TypeScript Compiler API-based identifier implementation search, "think" tool for improved coding performance, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Claude Crew Works
&lt;/h2&gt;

&lt;p&gt;Claude Crew provides both MCP for Claude Desktop integration and a CLI that comprehensively enhances Claude Desktop's functionality.&lt;/p&gt;

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

&lt;p&gt;In addition to Claude Desktop, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI API key for running local RAG (optional but recommended)&lt;/li&gt;
&lt;li&gt;Docker for running PostgreSQL for RAG searches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CLI offers interactive setup that outputs structured configuration for your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your-project
&lt;span class="nv"&gt;$ &lt;/span&gt;npx claude-crew@latest setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration is passed during MCP startup, allowing MCP to operate according to your project structure.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"claude-crew-claude-crew"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"claude-crew@latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"serve-mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/.claude-crew/config.json"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, it creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.claude-crew/instruction.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.claude-crew/memory-bank.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting &lt;code&gt;.claude-crew/instruction.md&lt;/code&gt; as Claude Project's custom instruction enables the coding agent functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running a Real Task
&lt;/h2&gt;

&lt;p&gt;Let's use Claude Crew to add a feature to Claude Crew itself. In this case, we'll add a "keep branch up-to-date" feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Since there is no mechanism to keep the branch up-to-date, please implement one.

Allow setting git's default branch when configuring via CLI
During prepare, if there are no local changes and we're on the default branch, do git pull --rebase origin [default branch]
Update the README to reflect the changes
After verifying the functionality, commit with a message in English

Let's begin.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once a task begins, the custom instruction invokes the "prepare" tool, which provides the LLM with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly relevant source code&lt;/li&gt;
&lt;li&gt;Relevant documentation&lt;/li&gt;
&lt;li&gt;Memory bank contents&lt;/li&gt;
&lt;li&gt;Project overview and tech stack information parsed from configuration and package.json&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using this context information, it explores for additional necessary information and performs coding tasks.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;claude-crew-write-file&lt;/code&gt; tool is used to update files, automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Returning type-checking results&lt;/li&gt;
&lt;li&gt;Returning ESLint results&lt;/li&gt;
&lt;li&gt;Detecting and running relevant tests and returning results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We want the output to pass tests and linting, but running these as MCP would increase round-trip communications, so they're built into MCP for efficiency.&lt;/p&gt;

&lt;p&gt;When implementation is complete, the custom instruction calls the &lt;code&gt;claude-crew-check-all&lt;/code&gt; tool to verify everything works correctly and completes the task.&lt;/p&gt;

&lt;p&gt;This process allows features to be implemented without human intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons and Challenges
&lt;/h2&gt;

&lt;p&gt;Here are some lessons learned and remaining challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP Inspector is Useful for Development
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/inspector" rel="noopener noreferrer"&gt;MCP Inspector&lt;/a&gt; is a valuable tool for debugging. It lets you test tools as if you were the LLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capturing stdout is Essential for Stability
&lt;/h3&gt;

&lt;p&gt;MCP uses standard input/output for communication, so using &lt;code&gt;console.log&lt;/code&gt; can cause MCP client errors due to invalid messages.&lt;/p&gt;

&lt;p&gt;I tried using a custom logger to avoid standard output during MCP usage, but some libraries inevitably needed it, so I overrode &lt;code&gt;process.stdout&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;// eslint-disable-next-line @typescript-eslint/unbound-method -- It's fine because we're just returning to a method with the same 'this'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalWrite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;myLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="k"&gt;return&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;// Process that outputs to stdout&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;originalWrite&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, permanently overriding &lt;code&gt;process.stdout.write&lt;/code&gt; would break MCP itself, so this approach must be used selectively. A cleaner solution would be preferable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long Tasks are Difficult with MCP
&lt;/h3&gt;

&lt;p&gt;Initially, I wanted the "prepare" tool to handle database migrations and re-indexing changed code, but debugging with MCP Inspector revealed timeout issues.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://qiita.com/7shi/items/3bf54f47a2d38c70d39b" rel="noopener noreferrer"&gt;this article&lt;/a&gt; explains, MCP Inspector times out after 10 seconds, while Claude Desktop allows 60 seconds. The client has the final say.&lt;/p&gt;

&lt;p&gt;Since the server can't request longer wait times for heavy tasks like "prepare," design must account for these constraints on long-running tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP Optimization Achieves Many Goals
&lt;/h3&gt;

&lt;p&gt;I've previously experimented with coding agents:&lt;br&gt;
&lt;a href="https://zenn.dev/bm_sms/articles/vercel_ai_sdk_mastra_ai_agent" rel="noopener noreferrer"&gt;Vercel AI SDK Mastra AI Agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While coding the agent lifecycle offers more flexibility, MCP and instructions can accomplish quite a lot on their own.&lt;/p&gt;

&lt;p&gt;The main advantages I observed were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RAG availability&lt;/li&gt;
&lt;li&gt;Optimized feedback during file operations&lt;/li&gt;
&lt;li&gt;Message compression for cost efficiency&lt;/li&gt;
&lt;li&gt;Dynamic system prompt modification during tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two can be achieved with MCP and configuration (plus CLI tools), while the latter two require complete implementation, which comes with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usage-based billing concerns&lt;/li&gt;
&lt;li&gt;Complex implementation challenges

&lt;ul&gt;
&lt;li&gt;Despite assistance from LLMs, Vercel AI SDK, Mastra, etc., implementing chat UIs and dynamically modifying agent system prompts involves difficult state management&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Starting with an MCP-first approach might be worthwhile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Understanding Could Be More Efficient
&lt;/h3&gt;

&lt;p&gt;In the task example, we hit character limits and had to request continuation. While some constraints are unavoidable, I'd like to minimize them.&lt;/p&gt;

&lt;p&gt;To improve context understanding and for better cost-efficiency than letting the system autonomously seek context, I included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RAG for codebase and source code&lt;/li&gt;
&lt;li&gt;Simplified memory bank

&lt;ul&gt;
&lt;li&gt;Unlike the original memory bank implementation with multiple files, Claude Crew uses a single file with reduced sections&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In the example, the prompt and context consumed about 5,500 tokens. I'm considering optimizations like choosing between memory bank and RAG to reduce this overhead.&lt;/p&gt;

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

&lt;p&gt;I've introduced Claude Crew, a tool I developed to enhance Claude Desktop's coding agent capabilities!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/claude-crew" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/claude-crew&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm continuing development with the goal of creating a tool that allows you to delegate relatively simple tasks entirely to Claude Desktop within your subscription limits.&lt;/p&gt;

&lt;p&gt;Please try it out! Contributions and stars are welcome and motivating!&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Reference: &lt;a href="https://www.anthropic.com/engineering/claude-think-tool" rel="noopener noreferrer"&gt;https://www.anthropic.com/engineering/claude-think-tool&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The embedding model costs approximately 10,000,000 tokens per dollar. Indexes are automatically kept up-to-date, but a content hash-based differential update logic is used to minimize updates.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Introduction to type-predicates-generator, which automatically generates type guards from TypeScript type definitions</title>
      <dc:creator>kimuson</dc:creator>
      <pubDate>Tue, 23 Nov 2021 05:48:54 +0000</pubDate>
      <link>https://dev.to/kimuson/introduction-to-type-predicates-generator-which-automatically-generates-type-guards-from-typescript-type-definitions-4bb9</link>
      <guid>https://dev.to/kimuson/introduction-to-type-predicates-generator-which-automatically-generates-type-guards-from-typescript-type-definitions-4bb9</guid>
      <description>&lt;p&gt;I've created a tool to automatically generate user-defined type guards (type predicate) and assertion functions from TypeScript type definitions. By automatically generating user-defined type guards, you can protect the types of your applications safely and easily without writing wrong implementation as type predicate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/type-predicates-generator" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/type-predicates-generator&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  type predicate and problems
&lt;/h2&gt;

&lt;p&gt;If you use type annotations or &lt;code&gt;as &amp;lt;type&amp;gt;&lt;/code&gt; for typing a value that comes from an external source such as API or JSON parsing, you won't be able to notice when you get an unexpected value.&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;Task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;titile&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;description&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;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="o"&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;parse&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="c1"&gt;// Write annotations for functions that return any type&lt;/span&gt;
&lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="cm"&gt;/* :task */&lt;/span&gt; &lt;span class="c1"&gt;// value is typed as Task even if the type is not match to the Task type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the type is different from what it actually is, it is undesirable because it reduces the benefits of TypeScript, both in terms of application safety and development experience.&lt;/p&gt;

&lt;p&gt;In such a case, you can use &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates" rel="noopener noreferrer"&gt;type predicate&lt;/a&gt; (&lt;code&gt;v is &amp;lt;type&amp;gt;&lt;/code&gt;) to do type guarding using a user-defined function.&lt;/p&gt;

&lt;p&gt;It allows you safe typing of untyped value.&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;// define type predicate&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Task&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&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="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!&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;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&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;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&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;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&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;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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;// using type predicate&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// if isTask returns true, assume task is of type Task&lt;/span&gt;
  &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="cm"&gt;/* :Task */&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 is safer than using &lt;code&gt;as&lt;/code&gt; or type annotations, but TypeScript does not take care of the correct implementation of this type predicate function.&lt;/p&gt;

&lt;p&gt;In the extreme case, a messed up implementation such as &lt;code&gt;const isTask = (v: unknown) v is Task =&amp;gt; true&lt;/code&gt; will narrow down the type to Task without getting angry.&lt;/p&gt;

&lt;p&gt;I don't think you ever write such an implementation, of course, but&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A case where the implementation was correct at the time of writing, but the &lt;code&gt;Task&lt;/code&gt; type is changed and isTask becomes an inappropriate implementation (adding a property)&lt;/li&gt;
&lt;li&gt;A simple implementation error (as you can see in &lt;code&gt;isTask&lt;/code&gt;, it is quite complicated to write object property checks properly, and there are also shared types, array child element checks, etc., so mistakes can be made)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In some cases, incorrect runtime checking functions may be introduced due to them.&lt;/p&gt;

&lt;p&gt;Also, since it is difficult to write type predicates for each type, psychologically speaking, it is easy to compromise with type annotations or &lt;code&gt;as&lt;/code&gt; without writing the type predicate itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to type-predicates-generator
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/d-kimuson/type-predicates-generator" rel="noopener noreferrer"&gt;type-predicates-generator&lt;/a&gt; solves these problems by automatically generating a type predicate function from a type definition.&lt;/p&gt;

&lt;p&gt;It can be installed from npm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/type-predicates-generator" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/type-predicates-generator&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; type-predicates-generator &lt;span class="c"&gt;# or npm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type predicate function will be generated automatically by passing the appropriate options to the &lt;code&gt;type-predicates-generator&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;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn run type-predicates-generator &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'path/to/types/**/*.ts'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'. /type-predicates.ts'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, automatically generates predicates functions from exported type declarations (type alias and interface) in files matching &lt;code&gt;path/to/types/**/*.ts&lt;/code&gt;, and writes them to &lt;code&gt;type-predicates.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you run type-predicates-generator on the &lt;code&gt;Task&lt;/code&gt; type used in the above example, it will automatically generate the following&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;// auto-generated predicate definitions&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Task&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;path/to/your-type-declare&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;const&lt;/span&gt; &lt;span class="nx"&gt;isTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;arg_0&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;arg_0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="nf"&gt;isNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;arg_0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="nf"&gt;isString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&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;arg_0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="nf"&gt;isString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&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;Now we can use the auto-generated function to protect our application by using it when values come in from the outside!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; import { isTask } from 'path/to/type-predicates'.
&lt;span class="err"&gt;
&lt;/span&gt; fetch("path/to/api").then(async (data) =&amp;gt; {
&lt;span class="gd"&gt;- const json: Task = await data.json(); // dangerous typing that doesn't check if it's really of type Task.
&lt;/span&gt;&lt;span class="gi"&gt;+ const json /* :any */ = await data.json();
+ if (!isTask(json)) throw new Error('Oops'); // throw an exception if the check fails
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;   json /* :Task */ }
 })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can safely and easily type values that come from the outside.&lt;/p&gt;

&lt;p&gt;If you specify the &lt;code&gt;-a&lt;/code&gt; option, &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-%20functions" rel="noopener noreferrer"&gt;assertion function&lt;/a&gt; can also be generated automatically. The assertion function is more appropriate for cases like the one above.&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;// which is additionally auto-generated by `-a` option&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;assertIsTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unkonwn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;asserts&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Task&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="nf"&gt;isTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`value must be Task but received &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Use&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="cm"&gt;/* :any */&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;data&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;assertIsTask&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="c1"&gt;// If it fails, an exception is raised&lt;/span&gt;
&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="cm"&gt;/* :Task */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since it is auto-generated, there is no need to write a predicate, and the psychological hurdle is low.&lt;/p&gt;

&lt;p&gt;It also supports watch mode (&lt;code&gt;-w&lt;/code&gt;), so you can run watch during development and reflect changes as they happen.&lt;/p&gt;

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

&lt;p&gt;See the repository for cli other options&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/type-predicates-generator#cli-options" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/type-predicates-generator#cli-options&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What can be checked and what can't
&lt;/h2&gt;

&lt;p&gt;Basically, I've tried to support all data structures that can be received as JSON (so if you find any missing, please raise an issue).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/type-predicates-generator/issues" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/type-predicates-generator/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions/Methods&lt;/li&gt;
&lt;li&gt;Promise&lt;/li&gt;
&lt;li&gt;Data structures with circular references (such as &lt;code&gt;obj1.recursive = obj2, obj2.recursive = obj1&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;When checking properties, they go to each other to check each other's properties, resulting in an infinite loop.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;It is not possible to perform checks in them.&lt;/p&gt;

&lt;p&gt;On the other hand, all type operations are supported.&lt;/p&gt;

&lt;p&gt;Complex types such as Mapped Types, Conditional Types, etc. can be generated without any problems, as long as they eventually resolve to JSON serializable types or their intersection or union types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// From: Partial using Mapped Types&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PartialTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Task&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;// Generated: generated from the last resolved type&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPartialTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;arg_0&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;PartialTask&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isUnion&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isNumber&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;
    &lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isUnion&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isString&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;
    &lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isUnion&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;isUndefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isString&lt;/span&gt;&lt;span class="p"&gt;])(&lt;/span&gt;&lt;span class="nx"&gt;arg_1&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;
    &lt;span class="nx"&gt;arg_0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&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;h2&gt;
  
  
  Use with openapi-generator
&lt;/h2&gt;

&lt;p&gt;In the front-end, some tools such as openapi-generator, aspida, etc. are used to automatically generate response types.&lt;/p&gt;

&lt;p&gt;It is also possible to include them directly in the type-predicates-generator generation, but since the type definitions tend to be huge and it takes a long time to generate them, you can re-export only the ones you use.&lt;/p&gt;

&lt;p&gt;(However, it took more than 5 seconds even when I tried it with a 4000-line type definition generated by &lt;a href="https://www.graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt;, which I use in my personal blog, so you may not have to worry about time to generate too much.)&lt;/p&gt;

&lt;p&gt;For this use case, I include not only the type declarations but also the re-exported type definitions in the generation&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="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Category&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;. /typescript-axios/api&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;There is a concrete example in the repository &lt;a href="https://github.com/d-kimuson/type-predicates-generator/tree/main/example" rel="noopener noreferrer"&gt;example&lt;/a&gt;. Types re-exported by &lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/example/types/re-export.ts#L4~L11" rel="noopener noreferrer"&gt;re-export.ts&lt;/a&gt; You can see that the function is generated in &lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/example/type-predicates.ts#L100~L124" rel="noopener noreferrer"&gt;type-predicate.ts&lt;/a&gt; from the type definition re-exported by &lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/example/type-predicates.ts#L100~L11" rel="noopener noreferrer"&gt;re-export.ts&lt;/a&gt;. From the type definition re-exported by &lt;a href="https://dev.to~L11"&gt;type-predicate.ts&lt;/a&gt;, we can see that the function has been generated&lt;/p&gt;

&lt;h2&gt;
  
  
  How is it implemented?
&lt;/h2&gt;

&lt;p&gt;The Compiler API extracts the type information from the Glob-specified file and generates it automatically.&lt;/p&gt;

&lt;p&gt;I'll leave the details of the Compiler API to another article.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;search &lt;a href="https://typescript-jp.gitbook.io/deep-dive/overview/ast#node" rel="noopener noreferrer"&gt;Node&lt;/a&gt; for the matched file and pick up the declaration node of type alias and interface. 2.&lt;/li&gt;
&lt;li&gt;recursively pick up the types from the declaration nodes using &lt;a href="https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker" rel="noopener noreferrer"&gt;TypeChecker&lt;/a&gt;, and 3. writes the exported type information as &lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/src/type-object.ts" rel="noopener noreferrer"&gt;Exportable Type Information&lt;/a&gt;, which is defined independently.&lt;/li&gt;
&lt;li&gt;generate code based on the exported type information&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is how it works&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/src/compiler-api/compiler-api-handler.ts" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/type-predicates-generator/blob/main/src/compiler-api/compiler-api-handler.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/d-kimuson/type-predicates-generator/blob/main/src/generate/generate-type-predicates.ts" rel="noopener noreferrer"&gt;https://github.com/d-kimuson/type-predicates-generator/blob/main/src/generate/generate-type-predicates.ts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other solutions
&lt;/h2&gt;

&lt;p&gt;There is a major library &lt;a href="https://www.npmjs.com/package/type-predicates-generator" rel="noopener noreferrer"&gt;io-ts&lt;/a&gt; that solves the problem that type predicate implementation may deviate from the type definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Usage Example&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isRight&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;fp-ts/lib/Either&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;t&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;io-ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TaskIO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&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="na"&gt;title&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&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="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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="o"&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;TypeOf&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;TaskIO&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="cm"&gt;/* :any */&lt;/span&gt; &lt;span class="o"&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;parse&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;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TaskIO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isRight&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="cm"&gt;/* :Task */&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;right&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;io-ts uses its own notation to define the types to be checked at runtime, and accepts TypeScript types from there (&lt;code&gt;t.TypeOf(typeof Task)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;It's a very nice library, but the type definitions can't be written in TypeScript types.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define an API type from an existing TS type through type operations.&lt;/li&gt;
&lt;li&gt;Define API types from existing TS types through type operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In such a case, type-predicates-generator is a good choice.&lt;/p&gt;

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

&lt;p&gt;So, that's my introduction to type-predicates-generator!&lt;br&gt;
It's still a work in progress, but it's an easy tool for improving type safety, so I hope you'll give it a try!&lt;br&gt;
PR and issues are welcome!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>VSCode Extension to expand hard-to-read type definitions in TypeScript</title>
      <dc:creator>kimuson</dc:creator>
      <pubDate>Fri, 28 May 2021 15:59:23 +0000</pubDate>
      <link>https://dev.to/kimuson/vscode-extensions-to-expand-hard-to-read-type-definitions-in-typescript-299</link>
      <guid>https://dev.to/kimuson/vscode-extensions-to-expand-hard-to-read-type-definitions-in-typescript-299</guid>
      <description>&lt;p&gt;I've created a VSCode extension that makes complex types easier to read, and I'll show you how to use it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;When I'm writing TypeScript, it sometimes hard-to-read complex types for me, so I often need to bind them to variables and use completion to find properties. I was wondering if there was something I could do to see the expanded types.&lt;/p&gt;

&lt;p&gt;I found out about TypeScript's &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API" rel="noopener noreferrer"&gt;CompilerAPI&lt;/a&gt;, so I thought it would be a good idea to extract the type and pass it to the VSCode Tree View, so I made it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I made
&lt;/h2&gt;

&lt;p&gt;An extension that can expand TypeScript type definitions&lt;/p&gt;

&lt;p&gt;You can install from &lt;a href="https://marketplace.visualstudio.com/items?itemName=kimuson.ts-type-expand" rel="noopener noreferrer"&gt;ts-type-expand - Visual Studio Marketplace&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Like this, You can expand and check the hard-to-read types on VSCode as many times as you need.&lt;/p&gt;

&lt;p&gt;If you hover over a variable, you will see the type information, but it sometimes hard to read like &lt;code&gt;XXX &amp;amp; YYY &amp;amp; ZZZ&lt;/code&gt; and you won't know what the final type is. This extension is useful in such cases.&lt;/p&gt;

&lt;p&gt;As for the supported types, &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API" rel="noopener noreferrer"&gt;CompilerAPI&lt;/a&gt; does the type resolution for you, so if TypeScript supports it, you should be able to expand all of them.&lt;/p&gt;

&lt;p&gt;As for valid nodes can be selected is shown in  &lt;a href="https://github.com/d-kimuson/ts-type-expand" rel="noopener noreferrer"&gt;repository&lt;/a&gt;, so please see it. but, you should be able to get types from most of the nodes you intuitively think you can get.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API" rel="noopener noreferrer"&gt;CompilerAPI&lt;/a&gt; retrieves the type information of the selected node on VSCode and passes it to the Tree View.&lt;/p&gt;

&lt;p&gt;After learning the basic usage by referring to the &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-%20the-type-checker" rel="noopener noreferrer"&gt;official material&lt;/a&gt;,  I created an extension to retrieve the type information.&lt;/p&gt;

&lt;p&gt;It was quite difficult because the necessary types for receiving Union types were not provided (the actual types existed, but there were no type definitions, so I had to find the properties by hand and use them), and the documentation was not very complete, so I did not know how to get the types I wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tree View API
&lt;/h2&gt;

&lt;p&gt;The extracted types are expanded in &lt;a href="https://code.visualstudio.com/api/extension-guides/tree-view" rel="noopener noreferrer"&gt;VSCode's TreeView&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This API is quite simple, so I was able to create it without too much trouble.&lt;/p&gt;

&lt;p&gt;However, the situation where we want to expand a type is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Properties&lt;/li&gt;
&lt;li&gt;Candidates for Union type&lt;/li&gt;
&lt;li&gt;Candidates for Enum&lt;/li&gt;
&lt;li&gt;Function expansion (arguments and return value)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when I tried to use it, I could understand that it could be expanded, but I couldn't understand why it could be expanded.&lt;/p&gt;

&lt;p&gt;Eventually.&lt;/p&gt;

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

&lt;p&gt;In this way, I have added information about what can be expanded (Properties, Union or Function).&lt;/p&gt;

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

&lt;p&gt;In this post, I introduced &lt;a href="https://marketplace.visualstudio.com/items?itemName=kimuson.ts-type-expand" rel="noopener noreferrer"&gt;ts-type-expand&lt;/a&gt;, an extension that can help you when you are reading hard to read types such as auto-generated types from GraphQL schemas or when the types provided by the library are difficult to understand.&lt;/p&gt;

&lt;p&gt;Please try it out!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
