<?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: Nathmaxx</title>
    <description>The latest articles on DEV Community by Nathmaxx (@nathmaxx).</description>
    <link>https://dev.to/nathmaxx</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%2F3919390%2F7dc9e6b5-e8a7-4f48-93de-359fe92fe6ff.png</url>
      <title>DEV Community: Nathmaxx</title>
      <link>https://dev.to/nathmaxx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nathmaxx"/>
    <language>en</language>
    <item>
      <title>Stop writing TypeScript interfaces by hand - generate them from JSON, CSV, and OpenAPI in one command</title>
      <dc:creator>Nathmaxx</dc:creator>
      <pubDate>Fri, 08 May 2026 07:55:01 +0000</pubDate>
      <link>https://dev.to/nathmaxx/stop-writing-typescript-interfaces-by-hand-generate-them-from-json-csv-and-openapi-in-one-561h</link>
      <guid>https://dev.to/nathmaxx/stop-writing-typescript-interfaces-by-hand-generate-them-from-json-csv-and-openapi-in-one-561h</guid>
      <description>&lt;p&gt;You're integrating a third-party API. You open the docs, find a sample response, and start typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// wait, is currency a string or an object?&lt;/span&gt;
    &lt;span class="c1"&gt;// what's the shape of variants[]?&lt;/span&gt;
    &lt;span class="c1"&gt;// does stock ever go null?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twenty minutes later you have a fragile interface you're not fully confident in — and the moment the API ships a new field, it's already stale.&lt;/p&gt;

&lt;p&gt;There's a better way.&lt;/p&gt;




&lt;h2&gt;
  
  
  snaptype: point it at the source, get types back
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://snaptype.dev" rel="noopener noreferrer"&gt;snaptype&lt;/a&gt; is a CLI that generates TypeScript interfaces and Zod schemas by reading your actual data — live API endpoints, OpenAPI specs, JSON files, CSV files.&lt;/p&gt;

&lt;p&gt;No config. No code to write. One command.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;from-url&lt;/code&gt; — types straight from a live endpoint
&lt;/h2&gt;

&lt;p&gt;This is the one I use most. Give it any JSON endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-url https://api.example.com/products &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/product.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;snaptype fetches the response and generates:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&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;EUR&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;GBP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&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;createdAt&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;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Variant&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Variant&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;sku&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;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;S&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;M&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;L&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;XL&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&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;EUR&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;GBP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="na"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iso&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VariantSchema&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;A few things worth noticing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nested objects are expanded&lt;/strong&gt; — &lt;code&gt;variants[]&lt;/code&gt; became its own &lt;code&gt;Variant&lt;/code&gt; interface automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enums are inferred&lt;/strong&gt; — &lt;code&gt;currency&lt;/code&gt; and &lt;code&gt;size&lt;/code&gt; had a small set of repeated values, so snaptype made them union types instead of &lt;code&gt;string&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nullables are detected&lt;/strong&gt; — &lt;code&gt;stock&lt;/code&gt; was &lt;code&gt;null&lt;/code&gt; in some responses, so it became &lt;code&gt;number | null&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic types&lt;/strong&gt; — &lt;code&gt;createdAt&lt;/code&gt; became &lt;code&gt;z.iso.datetime()&lt;/code&gt;, not a generic &lt;code&gt;z.string()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is inference against real data, not a naive field-by-field mapping.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-world example: GitHub API
&lt;/h2&gt;

&lt;p&gt;Point it at any real endpoint — here the GitHub user API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-url https://api.github.com/users/torvalds &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/github-user.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. You now have typed access to every field in that response — including nested objects — with Zod schemas you can use directly for runtime validation.&lt;/p&gt;

&lt;p&gt;When GitHub ships a new field, re-run the command. No manual diffing.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;from-openapi&lt;/code&gt; — one file per schema, from any spec
&lt;/h2&gt;

&lt;p&gt;If the API you're integrating has an OpenAPI or Swagger spec (most do), this is even better. Point it at the spec file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-openapi ./openapi.yaml &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or directly at the hosted spec URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-openapi https://petstore3.swagger.io/api/v3/openapi.json &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;snaptype reads every schema definition in the spec and generates one typed file per schema. YAML and JSON both work.&lt;/p&gt;

&lt;p&gt;For a spec that defines &lt;code&gt;Pet&lt;/code&gt;, &lt;code&gt;Order&lt;/code&gt;, and &lt;code&gt;User&lt;/code&gt;, you get three files:&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;// src/types/Pet.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;        &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;photoUrls&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;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;available&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;pending&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;sold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;      &lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;category&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// src/types/Order.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;        &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;petId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;     &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt;  &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;shipDate&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;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;placed&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;approved&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;delivered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;complete&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before, setting up a typed client from an OpenAPI spec meant:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finding (or writing) a code generator&lt;/li&gt;
&lt;li&gt;Configuring it&lt;/li&gt;
&lt;li&gt;Running it&lt;/li&gt;
&lt;li&gt;Cleaning up the generated mess&lt;/li&gt;
&lt;li&gt;Updating it every time the spec changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now it's one command.&lt;/p&gt;




&lt;h2&gt;
  
  
  Works with private and authenticated APIs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One-off request&lt;/strong&gt; — pass headers directly with &lt;code&gt;-H&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-url https://api.example.com/me &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/me.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Multiple endpoints on the same API&lt;/strong&gt; — store the headers in &lt;code&gt;.snaptyperc&lt;/code&gt; so you don't repeat yourself:&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;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"headers"&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;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer my-token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"X-Tenant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&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;Then every &lt;code&gt;from-url&lt;/code&gt; call picks them up automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-url /users &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/user.ts
npx snaptype from-url /products &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/product.ts
npx snaptype from-url /orders &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/order.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Headers set in &lt;code&gt;.snaptyperc&lt;/code&gt; are defaults — anything passed with &lt;code&gt;-H&lt;/code&gt; on the CLI takes priority if the same key appears in both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stdin fallback&lt;/strong&gt; — if the endpoint requires a flow you can't replicate in a single request (custom auth, cookies, proxy), pipe the response in from curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://api.example.com/me &lt;span class="se"&gt;\&lt;/span&gt;
  | npx snaptype from-stdin &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/me.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  JSON files and CSV too
&lt;/h2&gt;

&lt;p&gt;If you're working from a local file rather than a live endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Local JSON file&lt;/span&gt;
npx snaptype from-json ./user.json &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/user.ts

&lt;span class="c"&gt;# CSV export from a database or spreadsheet&lt;/span&gt;
npx snaptype from-csv ./orders.csv &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/order.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inference is the same — enums, nullables, semantic types, nested objects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Zero config to start
&lt;/h2&gt;

&lt;p&gt;No setup needed. If you want to pin defaults, add a &lt;code&gt;.snaptyperc&lt;/code&gt;:&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;"zod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/types"&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;Then every command just picks up those defaults automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it right now
&lt;/h2&gt;

&lt;p&gt;Run it directly with npx — no install needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx snaptype from-url https://api.github.com/users/torvalds &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/github-user.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or add it as a dev dependency if you want a fixed version and faster runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; snaptype
snaptype from-url https://api.github.com/users/torvalds &lt;span class="nt"&gt;--zod&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; src/types/github-user.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full docs at &lt;a href="https://snaptype.dev" rel="noopener noreferrer"&gt;snaptype.dev&lt;/a&gt; · Source on &lt;a href="https://github.com/Nathmaxx/snaptype" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If it saves you time, a ⭐ on the repo goes a long way — it helps other developers find the tool.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built this after one too many mornings spent re-typing interfaces from API docs. If from-url or from-openapi saves you time on a real project, drop a comment — I'm curious what APIs people are working with.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Feedback welcome
&lt;/h2&gt;

&lt;p&gt;snaptype is still early-stage and I'm actively shaping what it becomes. If you hit a use case it doesn't handle, a command that behaves unexpectedly, or a feature you'd find genuinely useful — open an issue on &lt;a href="https://github.com/Nathmaxx/snaptype/issues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or just leave a comment below. Every piece of feedback helps.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
