<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<atom:link href="https://jessewarden.com/feed" rel="self" type="application/rss+xml" />
	<link>https://jessewarden.com</link>
	<description>Software &#124; Fitness &#124; Gaming</description>
	<lastBuildDate>Wed, 01 Jul 2026 13:32:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://jessewarden.com/wp-content/uploads/2016/08/cropped-Lambda2-32x32.png</url>
	<title>Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<link>https://jessewarden.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Type Driven Development: Errors as Values</title>
		<link>https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html</link>
					<comments>https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Wed, 01 Jul 2026 13:30:22 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7030</guid>

					<description><![CDATA[Part 10 &#8211; Errors as Values This is a series of posts I’m writing about using types as another tool in software development, Continuous Delivery, &#38; keeping LLM’s honest. They’re also a design &#38; refactoring tool, a communication tool, and reduce how many tests you have to write. Errors as Values moves errors from a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Part 10 &#8211; Errors as Values</h2>



<p class="wp-block-paragraph">This is a series of posts I’m writing about using types as another tool in software development, Continuous Delivery, &amp; keeping LLM’s honest. They’re also a design &amp; refactoring tool, a communication tool, and reduce how many tests you have to write.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary><strong>Parts</strong></summary>
<ol class="wp-block-list">
<li><a href="https://jessewarden.com/2026/06/type-driven-development-branded-types.html">Part 1 &#8211; Branded Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-product-types.html">Part 2 &#8211; Product Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unions-and-discriminated-unions.html">Part 3 &#8211; Union &amp; Discriminated Unions</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-non-empty-collections.html">Part 4 &#8211; Non-Empty Collections</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-indexed-types.html">Part 5 &#8211; Indexed Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html">Part 6 &#8211; unknown vs any</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-result.html">Part 7 &#8211; Result</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-schema.html">Part 8 &#8211; Schema</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-total-function.html">Part 9 &#8211; Total Function</a></li>



<li>Part 10 &#8211; Errors as Values</li>
</ol>
</details>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="594" height="1000" src="https://jessewarden.com/wp-content/uploads/2026/07/stringly-typed-failures.png" alt="" class="wp-image-7026" srcset="https://jessewarden.com/wp-content/uploads/2026/07/stringly-typed-failures.png 594w, https://jessewarden.com/wp-content/uploads/2026/07/stringly-typed-failures-178x300.png 178w" sizes="(max-width: 594px) 100vw, 594px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" width="600" height="998" src="https://jessewarden.com/wp-content/uploads/2026/07/errors-as-values.png" alt="" class="wp-image-7027" srcset="https://jessewarden.com/wp-content/uploads/2026/07/errors-as-values.png 600w, https://jessewarden.com/wp-content/uploads/2026/07/errors-as-values-180x300.png 180w" sizes="(max-width: 600px) 100vw, 600px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">Errors as Values moves errors from a random, runtime consequence to an iterative design process using types. u intentionally think about &amp; design what could go wrong w/your code in functions, libraries/back-ends u integrate with &amp; your application. Let&#8217;s fix fetch to see how this all works.</p>



<span id="more-7030"></span>



<p class="wp-block-paragraph">We&#8217;ve talked about the 4 error types in the past:</p>



<ol class="wp-block-list">
<li>domain</li>



<li>infrastructure</li>



<li>panic</li>



<li>unforeseen</li>
</ol>



<p class="wp-block-paragraph">If u don&#8217;t know where an Error goes in the above list, 1st can u or the user do anything about it? If no, then 3.</p>



<p class="wp-block-paragraph">2nd, ask your Product/Business Owner. If they look confused it&#8217;s 2, else it is 1.</p>



<p class="wp-block-paragraph">fetch is infrastructure; we use it to make http calls, but it&#8217;s painful to work w/; <code>Promise&lt;Response&gt;</code> as a return value lies, having to check <code>response.ok</code> first, _then_ attempt <code>response.json()</code>, etc. Numerous exceptions, order of operation issues, none of it type-safe. 1 thing can go right: Your schema passes. Let&#8217;s narrow what can go wrong: only 4 things: it timed out, got a 4xx/5xx status, a network http 0 error, or your schema failed. Let&#8217;s model that as a Discriminated Union to narrow what can go wrong:</p>


<pre class="wp-block-code"><span><code class="hljs">type FetchError = Timeout | BadStatus | NetworkErr | BadBody</code></span></pre>


<p class="wp-block-paragraph">Why not just a Union? When we get a <code>BadStatus</code>, what was the status code? When we get a <code>BadBody</code> was it the JSON failing to parse, or it parsed by didn&#8217;t match the schema, &amp; on what part(s)? DU&#8217;s hold data + ensure we only access that data for that particular type.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type Timeout = { <span class="hljs-attr">tag</span>: <span class="hljs-string">'Timeout'</span>, <span class="hljs-attr">time</span>: Seconds }
type BadStatus = { <span class="hljs-attr">tag</span>: <span class="hljs-string">'BadStatus'</span>, <span class="hljs-attr">code</span>: HttpStatusCode }
type NetworkErr = { ... }
type BadBody = { <span class="hljs-attr">tag</span>: <span class="hljs-string">'BadBody'</span>, <span class="hljs-attr">zodErrors</span>: ZodError&#91;] }</code></span></pre>


<p class="wp-block-paragraph">Now we can write a more total, safer function to fetch data:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml">type get = <span class="hljs-tag">&lt;<span class="hljs-name">T</span>&gt;</span>(s:ZodSchema<span class="hljs-tag">&lt;<span class="hljs-name">T</span>&gt;</span>, url:string) =&gt;
  Result<span class="hljs-tag">&lt;<span class="hljs-name">T,</span> <span class="hljs-attr">FetchError</span>&gt;</span></code></span></pre>


<p class="wp-block-paragraph">Then you wrap fetch with code to convert to our 4 errors:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">try</span> {

  <span class="hljs-keyword">const</span> response = fetch(...)

  <span class="hljs-comment">// handle bad status</span>
  <span class="hljs-keyword">if</span>(!response.ok) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">tag</span>: <span class="hljs-string">'BadStatus'</span>, <span class="hljs-attr">code</span>: response.status }

  <span class="hljs-comment">// handle timeouts</span>
  <span class="hljs-keyword">if</span>(error.name === <span class="hljs-string">'AbortError'</span>) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">tag</span>: <span class="hljs-string">'Timeout'</span>, ... }</code></span></pre>


<p class="wp-block-paragraph">Benefits of this hard work? Fetch is no longer imperative &amp; its now type-safe. A single switch statement handles only 4 unhappy paths:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-keyword">switch</span>(r.tag) {
  <span class="hljs-keyword">case</span> <span class="hljs-string">'Timeout'</span>: ...
  <span class="hljs-keyword">case</span> <span class="hljs-string">'BadStatus'</span>: ...
  <span class="hljs-keyword">case</span> <span class="hljs-string">'NetworkErr'</span>: ...
  <span class="hljs-keyword">case</span> <span class="hljs-string">'BadBody'</span>: ...</code></span></pre>


<p class="wp-block-paragraph">BUT you still have the option to retry, convert to another error type, or recover, all in a type-safe way.</p>



<p class="wp-block-paragraph">Our Product Owner wants a new Domain Error if account is not activated:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type NotActivated = { <span class="hljs-attr">tag</span>: <span class="hljs-string">'NotActivated'</span> }

<span class="hljs-keyword">if</span>(!account.activated) {
  <span class="hljs-keyword">return</span> err({ <span class="hljs-attr">tag</span>: <span class="hljs-string">'NotActivated'</span> })</code></span></pre>


<p class="wp-block-paragraph">Even in happy path, we can have errors; we model them intentionally in our Domain, the compiler ensures we handle them as our code grows.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Type Driven Development: Total Function</title>
		<link>https://jessewarden.com/2026/06/type-driven-development-total-function.html</link>
					<comments>https://jessewarden.com/2026/06/type-driven-development-total-function.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Tue, 30 Jun 2026 12:21:41 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7003</guid>

					<description><![CDATA[Part 9 &#8211; Total Function This is a series of posts I’m writing about using types as another tool in software development, Continuous Delivery, &#38; keeping LLM’s honest. They’re also a design &#38; refactoring tool, a communication tool, and reduce how many tests you have to write. Type safety is a spectrum. A gradual type [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Part 9 &#8211; Total Function</h2>



<p class="wp-block-paragraph">This is a series of posts I’m writing about using types as another tool in software development, Continuous Delivery, &amp; keeping LLM’s honest. They’re also a design &amp; refactoring tool, a communication tool, and reduce how many tests you have to write.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary><strong>Parts</strong></summary>
<ol class="wp-block-list">
<li><a href="https://jessewarden.com/2026/06/type-driven-development-branded-types.html">Part 1 &#8211; Branded Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-product-types.html">Part 2 &#8211; Product Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unions-and-discriminated-unions.html">Part 3 &#8211; Union &amp; Discriminated Unions</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-non-empty-collections.html">Part 4 &#8211; Non-Empty Collections</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-indexed-types.html">Part 5 &#8211; Indexed Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html">Part 6 &#8211; unknown vs any</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-result.html">Part 7 &#8211; Result</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-schema.html">Part 8 &#8211; Schema</a></li>



<li>Part 9 &#8211; Total Function</li>



<li><a href="https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html">Part 10 &#8211; Errors as Values</a></li>
</ol>
</details>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" width="594" height="996" src="https://jessewarden.com/wp-content/uploads/2026/06/partial-functions.png" alt="" class="wp-image-7009" srcset="https://jessewarden.com/wp-content/uploads/2026/06/partial-functions.png 594w, https://jessewarden.com/wp-content/uploads/2026/06/partial-functions-179x300.png 179w" sizes="(max-width: 594px) 100vw, 594px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="600" height="996" src="https://jessewarden.com/wp-content/uploads/2026/06/total-functions.png" alt="" class="wp-image-7010" srcset="https://jessewarden.com/wp-content/uploads/2026/06/total-functions.png 600w, https://jessewarden.com/wp-content/uploads/2026/06/total-functions-181x300.png 181w" sizes="auto, (max-width: 600px) 100vw, 600px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">Type safety is a spectrum. A gradual type system widens the spectrum in a good &amp; bad way; u have flexibility to discover your domain as it emerges w/less strict types + integrate w/less typed &amp; legacy systems. That has a cost in safety. Sometimes u can narrow what&#8217;s allowed through types, then expand to other possibilities as you learn more. Whatever you choose, aim to design Total Functions; every input returns a <em>sensible</em> value.</p>



<span id="more-7003"></span>



<p class="wp-block-paragraph">Most functions we create are called Partial Functions; functions that throw/crash, or return nonsensical inputs for some inputs.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type Divide = <span class="hljs-function">(<span class="hljs-params">a:number, b:number</span>) =&gt;</span> number</code></span></pre>


<p class="wp-block-paragraph">Divide looks like a normal function; notice I only provided the type signature. From that you can figure out how the function works:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">divide(<span class="hljs-number">12</span>, <span class="hljs-number">6</span>) <span class="hljs-comment">// 2</span>
divide(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>) <span class="hljs-comment">// 2</span></code></span></pre>


<p class="wp-block-paragraph">What about 2 / 0? That&#8217;s infinity. Technically it&#8217;s a number type, but is that what I want? What about 0 / 0? That&#8217;s NaN. While it&#8217;s called &#8220;NOT a number&#8221;, it&#8217;s also technically a number. Perhaps I just want numbers I can show the user? That means division can fail, so let&#8217;s fix the type:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type Divide = <span class="hljs-function">(<span class="hljs-params">…, …</span>) =&gt;</span> Result

divide = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> n = a / b
  <span class="hljs-keyword">if</span>(nIsAGoodInteger(n)) {
    <span class="hljs-keyword">return</span> ok(n)
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> err(…)
  }</code></span></pre>


<p class="wp-block-paragraph">Now it&#8217;s more clear; infinity, negative infinity, &amp; NaN will cause an error. But this is awkward to use; math requires error checking now? Blech… what if we ensure the inputs are good instead?</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type Divide = <span class="hljs-function">(<span class="hljs-params">a:number, b:PositiveInteger</span>) =&gt;</span> number</code></span></pre>


<p class="wp-block-paragraph">Much easier to work w/ + expected outputs. More total.</p>



<p class="wp-block-paragraph">What about fetch? Many would say:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type fetch = <span class="hljs-function">(<span class="hljs-params">url:string</span>) =&gt;</span> <span class="hljs-built_in">Promise</span>&lt;Response&gt;</code></span></pre>


<p class="wp-block-paragraph">but technically it can also crash; u have no internet, u provide a bad URL, JSON fails to parse, blah blah blah. A more total signature would be:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml">type safeFetch = <span class="hljs-tag">&lt;<span class="hljs-name">T</span>&gt;</span>(url:string) =&gt; 
  ResultAsync<span class="hljs-tag">&lt;<span class="hljs-name">T,</span> <span class="hljs-attr">FetchError</span>&gt;</span></code></span></pre>


<p class="wp-block-paragraph">We &#8220;expect&#8221; some type to be returned from our service; that implies a Schema is involved. It&#8217;s not a <code>Result</code>, but a <code>ResultAsync</code>, which implies a <code>Promise</code>. The error is specifically a <code>FetchError</code> type. The name has &#8220;safe&#8221; in it, implying no exceptions thrown. All that from just reading the type signature. More total.</p>



<p class="wp-block-paragraph">Partial functions have type signatures that lie to you. They say &#8220;Oh yeah I return a Promise&lt;T&gt;&#8221;, but all kinds of bad things happen the type signature doesn&#8217;t tell you about. The <code>ResultAsync&lt;T, FetchError&gt;</code> is extremely clear &amp; thorough.</p>



<p class="wp-block-paragraph">Once u start composing these functions together to make programs, that makes your code more total. &#8220;when it compiles it works&#8221; is more likely to be true. Your app&#8217;s type signature, whether UI or API, is more likely to be total.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type AWSLambda = <span class="hljs-function">(<span class="hljs-params">event:APIGatewayProxyEvent</span>) =&gt;</span>
  ResultAsync&lt;HttpResponse, never&gt;</code></span></pre>]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/06/type-driven-development-total-function.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Type Driven Development: Schema</title>
		<link>https://jessewarden.com/2026/06/type-driven-development-schema.html</link>
					<comments>https://jessewarden.com/2026/06/type-driven-development-schema.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Tue, 30 Jun 2026 12:18:03 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=7004</guid>

					<description><![CDATA[Part 8 &#8211; Schema This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &#38; keeping LLM&#8217;s honest. They&#8217;re also a design &#38; refactoring tool, a communication tool, and reduce how many tests you have to write. To do anything of value in software, we have [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Part 8 &#8211; Schema</h2>



<p class="wp-block-paragraph">This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &amp; keeping LLM&#8217;s honest. They&#8217;re also a design &amp; refactoring tool, a communication tool, and reduce how many tests you have to write.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary><strong>Parts</strong></summary>
<ol class="wp-block-list">
<li><a href="https://jessewarden.com/2026/06/type-driven-development-branded-types.html">Part 1 &#8211; Branded Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-product-types.html">Part 2 &#8211; Product Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unions-and-discriminated-unions.html">Part 3 &#8211; Union &amp; Discriminated Unions</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-non-empty-collections.html">Part 4 &#8211; Non-Empty Collections</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-indexed-types.html">Part 5 &#8211; Indexed Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html">Part 6 &#8211; unknown vs any</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-result.html">Part 7 &#8211; Result</a></li>



<li>Part 8 &#8211; Schema</li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-total-function.html">Part 9 &#8211; Total Function</a></li>



<li><a href="https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html">Part 10 &#8211; Errors as Values</a></li>
</ol>
</details>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="592" height="990" src="https://jessewarden.com/wp-content/uploads/2026/06/drift.png" alt="" class="wp-image-7005" srcset="https://jessewarden.com/wp-content/uploads/2026/06/drift.png 592w, https://jessewarden.com/wp-content/uploads/2026/06/drift-179x300.png 179w" sizes="auto, (max-width: 592px) 100vw, 592px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="594" height="992" src="https://jessewarden.com/wp-content/uploads/2026/06/schema.png" alt="" class="wp-image-7006" srcset="https://jessewarden.com/wp-content/uploads/2026/06/schema.png 594w, https://jessewarden.com/wp-content/uploads/2026/06/schema-180x300.png 180w" sizes="auto, (max-width: 594px) 100vw, 594px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">To do anything of value in software, we have to get unsafe data from outside our type system into it. We saw how unknown forces us to type narrow, but type narrowing is dangerous, tedious, and it&#8217;s hard to be thorough.</p>



<span id="more-7004"></span>


<pre class="wp-block-code"><span><code class="hljs language-javascript">cow = <span class="hljs-built_in">JSON</span>.parse(json)
<span class="hljs-keyword">if</span>(cow 
  &amp;&amp; <span class="hljs-string">'age'</span> <span class="hljs-keyword">in</span> cow 
  &amp;&amp; <span class="hljs-keyword">typeof</span> cow?.age === <span class="hljs-string">'number'</span>)
  <span class="hljs-comment">// could be NaN</span></code></span></pre>


<p class="wp-block-paragraph">Then comes the architecture problem; how do you DRY (Don&#8217;t Repeat Yourself) this? Multiple parts of your code have:</p>


<pre class="wp-block-code"><span><code class="hljs">type Cow = { age: number }</code></span></pre>


<p class="wp-block-paragraph">But later the back-end changes age to be optional:</p>


<pre class="wp-block-code"><span><code class="hljs">type Cow = { age?: number }</code></span></pre>


<p class="wp-block-paragraph">So you have to update both your types and parsing code. This occurs a lot, which then creates Shotgun Parsing all throughout your code:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">if</span>(cow.age) {
  <span class="hljs-comment">// use age</span>
} <span class="hljs-keyword">else</span> {
  <span class="hljs-comment">// throw an error</span>
}</code></span></pre>


<p class="wp-block-paragraph">This is because despite types, no one can trust the data. No code knows where the data came from; &#8220;Maybe age hasn&#8217;t been validated yet? Better validate just in case.&#8221; You started coupling the types through your code in hopes everyone would know &#8220;what a Cow is&#8221;, but now all the code is repeatedly validating the data. Worse, only parts are validated:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">if</span>(cow.name) {
<span class="hljs-comment">// if no name, throws an error</span>
<span class="hljs-comment">// what about age? Who knows</span></code></span></pre>


<p class="wp-block-paragraph">Even code formatting, e.g. Oxcfmt/Prettier/Biome, is bypassed b/c data is at runtime, so Python snake case data:</p>


<pre class="wp-block-code"><span><code class="hljs language-css">{ <span class="hljs-attribute">first_name</span>: <span class="hljs-string">'Moo'</span>, last_name: <span class="hljs-string">'Cow'</span> }</code></span></pre>


<p class="wp-block-paragraph">Can start infecting your camelCase style code. Since validation is often impromptu, it&#8217;s not all the same or thorough. Empty strings &#8221;, NaN for numbers, and optional properties on data cause runtime errors or null checks like <code>if(thing?.and?.some?.prop)</code> adding lots of validation code repeatedly.</p>



<p class="wp-block-paragraph">Lastly, the data you get isn&#8217;t always what you want. REST API&#8217;s can send back 100 JSON values, but you only need 2, forcing you to write &amp; maintain a lot of parsing code you&#8217;ll never use. JSON can have optional values, but you require that data, knowingly parsing the thing you don&#8217;t like.</p>



<p class="wp-block-paragraph">Schema&#8217;s solve all this. 1 source of truth, it either parses or it doesn&#8217;t, the type is validated data all of your code can trust, use without modifying, and not have to validate. The shape can be what you want/need instead of coupling to what the back-end gives you, then having to update all your code when the back-end changes. Zod/ArkType/Effect all provide schemas:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-comment">// define your parsing functions</span>
cowSchema = z.object({
  <span class="hljs-comment">// a number that is not NaN and positive</span>
  <span class="hljs-attr">age</span>: z.number().gte(<span class="hljs-number">0</span>),
  <span class="hljs-comment">// a string name instead of Python's snake case first_name</span>
  <span class="hljs-attr">name</span>: z.string().transform( <span class="hljs-function"><span class="hljs-params">d</span> =&gt;</span> ({ …d, <span class="hljs-attr">name</span>: d.first_name }) )
})

<span class="hljs-comment">// use it to create your type</span>
type Cow = z.infer&lt;<span class="hljs-keyword">typeof</span> cowSchema&gt;

<span class="hljs-comment">// parse your data</span>
json = <span class="hljs-built_in">JSON</span>.parse(data)
cow = cowSchema.parse(json)
<span class="hljs-comment">// cow is a Cow type and safe to use!</span></code></span></pre>


<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/06/type-driven-development-schema.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Type Driven Development: Result</title>
		<link>https://jessewarden.com/2026/06/type-driven-development-result.html</link>
					<comments>https://jessewarden.com/2026/06/type-driven-development-result.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sun, 28 Jun 2026 11:18:44 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=6980</guid>

					<description><![CDATA[Part 7 &#8211; Result This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &#38; keeping LLM&#8217;s honest. They&#8217;re also a design &#38; refactoring tool, a communication tool, and reduce how many tests you have to write. Good type systems create pure &#38; total functions. Where [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Part 7 &#8211; Result</h2>



<p class="wp-block-paragraph">This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &amp; keeping LLM&#8217;s honest. They&#8217;re also a design &amp; refactoring tool, a communication tool, and reduce how many tests you have to write.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary><strong>Parts:</strong></summary>
<ol class="wp-block-list">
<li><a href="https://jessewarden.com/2026/06/type-driven-development-branded-types.html">Part 1 &#8211; Branded Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-product-types.html">Part 2 &#8211; Product Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unions-and-discriminated-unions.html">Part 3 &#8211; Union &amp; Discriminated Unions</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-non-empty-collections.html">Part 4 &#8211; Non-Empty Collections</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-indexed-types.html">Part 5 &#8211; Indexed Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html">Part 6 &#8211; unknown vs any</a></li>



<li>Part 7 &#8211; Result</li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-schema.html">Part 8 &#8211; Schema</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-total-function.html">Part 9 &#8211; Total Function</a></li>



<li><a href="https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html">Part 10 &#8211; Errors as Values</a></li>
</ol>
</details>



<p class="wp-block-paragraph">Good type systems create pure &amp; total functions. Where does that leave errors? In programming, we have 4 types of errors:</p>



<ol class="wp-block-list">
<li>those we create in our domain</li>



<li>those we expect from infrastructure</li>



<li>situations where we cannot recover</li>



<li>those we weren&#8217;t expecting, hence &#8220;exceptional&#8221; situations</li>
</ol>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="588" height="992" src="https://jessewarden.com/wp-content/uploads/2026/06/exception-blindness.png" alt="" class="wp-image-6981" srcset="https://jessewarden.com/wp-content/uploads/2026/06/exception-blindness.png 588w, https://jessewarden.com/wp-content/uploads/2026/06/exception-blindness-178x300.png 178w" sizes="auto, (max-width: 588px) 100vw, 588px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="596" height="996" src="https://jessewarden.com/wp-content/uploads/2026/06/result-types.png" alt="" class="wp-image-6982" srcset="https://jessewarden.com/wp-content/uploads/2026/06/result-types.png 596w, https://jessewarden.com/wp-content/uploads/2026/06/result-types-180x300.png 180w" sizes="auto, (max-width: 596px) 100vw, 596px" /></figure>
</div>
</div>



<span id="more-6980"></span>



<p class="wp-block-paragraph">If a type system has Discriminated Unions (sum / variant types), then that&#8217;s what we use for 1 &amp; 2, the majority of what programmers deal w/.</p>


<pre class="wp-block-code"><span><code class="hljs">type FetchError 
  = BadURL 
  | BadBody 
  | BadStatus 
  | NetworkError 
  | Timeout</code></span></pre>


<p class="wp-block-paragraph">Unless you&#8217;re dealing w/important hardware situations like Rust&#8217;s panics, we just ignore 3 b/c you can&#8217;t do anything anyway. 4 will &#8220;go away&#8221; if you focus on 1 &amp; 2.</p>



<p class="wp-block-paragraph">Modelling errors w/Unions poses a problem from a Domain Driven Design perspective: how do you differentiate 2 paths; happy &amp; unhappy? The FP world has settled on a Result type:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml">type Result<span class="hljs-tag">&lt;<span class="hljs-name">T,</span> <span class="hljs-attr">E</span>&gt;</span>
  = Ok<span class="hljs-tag">&lt;<span class="hljs-name">T</span>&gt;</span>
  | Err<span class="hljs-tag">&lt;<span class="hljs-name">E</span>&gt;</span></code></span></pre>


<p class="wp-block-paragraph">It has 2 type parameters; T type for happy path data, E error type for unhappy path.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type FetchResult&lt;<span class="hljs-built_in">Array</span>&lt;Person&gt;, FetchError&gt;</code></span></pre>


<p class="wp-block-paragraph">However, E in practice never is just 1 error for long. As you start composing more functions together that can fail, you start creating anonymous unions. For example, if we read from an environment variable for our secrets:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type ReadSecrets = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span>
  Result&lt;Secrets, ReadError&gt;</code></span></pre>


<p class="wp-block-paragraph">&#8230; then call fetch, our return type for that function would be both errors:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">type fetchPeople = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> 
  Result&lt;<span class="hljs-built_in">Array</span>&lt;Person&gt;, ReadError | FetchError&gt;</code></span></pre>


<p class="wp-block-paragraph">Those anonymous unions of errors, e.g. <code>ReadError | FetchError</code>, start happening a lot. The type system ensures through exhaustiveness checking you handle all errors. You also discover more about your domain through what can go wrong.</p>



<p class="wp-block-paragraph">Testing is straight forward b/c the happy path is just <code>Ok&lt;T&gt;</code>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">stubFetch = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> ok(&#91; person ])</code></span></pre>


<p class="wp-block-paragraph">&amp; unhappy is an <code>Err&lt;E&gt;</code>:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">stubBadFetch = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> err(b00m b00m)</code></span></pre>


<p class="wp-block-paragraph">You still have the flexibility to recover from each error; e.g. if secrets can&#8217;t be read from environment variables, you can fetch from a service. Others, like a fetch error <code>BadStatus&lt;429&gt;</code>, you could retry. Why not try/catch? Result is type safe + ensures all are handled.</p>



<p class="wp-block-paragraph">Result gives you a convention for error handling + separating happy/unhappy paths; u still retain the ability to create DDD Domain errors &#8220;PersonUnauthorized&#8221;, infrastructure &#8220;FetchError&#8221;, &amp; Panics like &#8220;CantReadSecrets&#8221; that u can map to a throw/panic (or Effect.die). You no longer use try/catch unless you&#8217;re mapping known unsafe (or potentially unsafe) code to a Result:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">const</span> json = <span class="hljs-built_in">JSON</span>.parse(data)
  <span class="hljs-keyword">return</span> ok(json)
} <span class="hljs-keyword">catch</span>(error) {
  <span class="hljs-keyword">return</span> err(error)
}</code></span></pre>


<p class="wp-block-paragraph">We&#8217;ll talk more in the future about how to model Errors as Values &amp; build applications on top of Result, and the benefits of doing so.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/06/type-driven-development-result.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Type Driven Development: unknown vs any</title>
		<link>https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html</link>
					<comments>https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html#respond</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sat, 27 Jun 2026 22:58:47 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://jessewarden.com/?p=6974</guid>

					<description><![CDATA[Part 6 &#8211; unknown vs any This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &#38; keeping LLM&#8217;s honest. They&#8217;re also a design &#38; refactoring tool, a communication tool, and reduce how many tests you have to write. While good type systems give you confidence [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Part 6 &#8211; unknown vs any</h2>



<p class="wp-block-paragraph">This is a series of posts I&#8217;m writing about using types as another tool in software development, Continuous Delivery, &amp; keeping LLM&#8217;s honest. They&#8217;re also a design &amp; refactoring tool, a communication tool, and reduce how many tests you have to write.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary><strong>Parts:</strong></summary>
<ol class="wp-block-list">
<li><a href="https://jessewarden.com/2026/06/type-driven-development-branded-types.html">Part 1 &#8211; Branded Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-product-types.html">Part 2 &#8211; Product Types</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-unions-and-discriminated-unions.html">Part 3 &#8211; Union &amp; Discriminated Unions</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-non-empty-collections.html">Part 4 &#8211; Non-Empty Collections</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-indexed-types.html">Part 5 &#8211; Indexed Types</a></li>



<li>Part 6 &#8211; unknown vs any</li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-result.html">Part 7 &#8211; Result</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-schema.html">Part 8 &#8211; Schema</a></li>



<li><a href="https://jessewarden.com/2026/06/type-driven-development-total-function.html">Part 9 &#8211; Total Function</a></li>



<li><a href="https://jessewarden.com/2026/07/type-driven-development-errors-as-values.html">Part 10 &#8211; Errors as Values</a></li>
</ol>
</details>



<p class="wp-block-paragraph">While good type systems give you confidence &#8220;when it compiles, it works&#8221;, and enables fearless refactoring, we&#8217;re often getting data _into_ our type system that isn&#8217;t typed.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="600" height="996" src="https://jessewarden.com/wp-content/uploads/2026/06/any.png" alt="" class="wp-image-6975" srcset="https://jessewarden.com/wp-content/uploads/2026/06/any.png 600w, https://jessewarden.com/wp-content/uploads/2026/06/any-181x300.png 181w" sizes="auto, (max-width: 600px) 100vw, 600px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="616" height="994" src="https://jessewarden.com/wp-content/uploads/2026/06/unknown.png" alt="" class="wp-image-6976" srcset="https://jessewarden.com/wp-content/uploads/2026/06/unknown.png 616w, https://jessewarden.com/wp-content/uploads/2026/06/unknown-186x300.png 186w" sizes="auto, (max-width: 616px) 100vw, 616px" /></figure>
</div>
</div>



<span id="more-6974"></span>


<pre class="wp-block-code"><span><code class="hljs language-javascript">whatIsThisWhoKnows = <span class="hljs-keyword">await</span> response.json()</code></span></pre>


<p class="wp-block-paragraph">How you handle this depends on the type system, but for Gradually Typed ones like Luau, Python, and TypeScript, you have 2 options with various trade offs: any and unknown (Python calls it Any / object).</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> person = <span class="hljs-built_in">JSON</span>.parse(data) <span class="hljs-keyword">as</span> any
<span class="hljs-comment">// <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Compiler allows this dangerous code </span>
<span class="hljs-comment">// because person's type is any</span>
<span class="hljs-built_in">console</span>.log(person.name)</code></span></pre>


<p class="wp-block-paragraph">Any turns the type system off. This sounds horrifying at first, but it&#8217;s also why gradual type systems are so popular; they enable you to git-r-done, you can integrate w/untyped code namely libraries/modules you didn&#8217;t write, or when dealing w/3rd party data that you aren&#8217;t really sure what the type is.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> figureOutWhatThisIs:any = JWT.validate(jsonWebToken) <span class="hljs-keyword">as</span> any
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"figureOutWhatThisIs:"</span>, figureOutWhatThisIs)</code></span></pre>


<p class="wp-block-paragraph">Despite types software has a rule of &#8220;we have to run it to know what it does&#8221; and even in something type-powerful like Elm/Scala/Haskell, sometimes we need to run the code to &#8220;see&#8221; or log the data, especially from some 3rd party / code that isn&#8217;t ours. I can&#8217;t count how many times a REST API said it delivered one thing, but ended up delivering something either slightly or completely different. Other times you just set your types up wrong, and need to test &#8217;em at runtime.</p>



<p class="wp-block-paragraph">That said, if you want to be type-safe, and practice Type Driven Development, you should avoid any. Any turns off the type system, so all the work you did on creating types can be negated by one mis-typed any slipping in. Instead, we should be using types to _narrow_ what we want and instead using the unknown type helps us do that.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">const</span> person = <span class="hljs-built_in">JSON</span>.parse(data) <span class="hljs-keyword">as</span> unknown
<span class="hljs-comment">// <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Compiler does NOT allow this, </span>
<span class="hljs-comment">// have to type narrow first</span>
<span class="hljs-built_in">console</span>.log(person.name)</code></span></pre>


<p class="wp-block-paragraph">For now, recognize any is a tool to explicitly turn off the TypeScript compiler. If you can, try to use unknown instead, and type narrow to what you _think_ it should be. If it fails at runtime, type narrow to that, then try again. This ensures data coming from outside must be type narrowed first, and you can add extra unit &amp; fuzz/property tests on this part as well to help.</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript"><span class="hljs-keyword">if</span>(personMaybe
  &amp;&amp; <span class="hljs-keyword">typeof</span> personMaybe === <span class="hljs-string">'object'</span>
  &amp;&amp; <span class="hljs-string">'name'</span> <span class="hljs-keyword">in</span> personMaybe
  &amp;&amp; <span class="hljs-keyword">typeof</span> personMaybe?.name === <span class="hljs-string">'string'</span>) {
    <span class="hljs-comment">// then we're probably safe here </span>
    <span class="hljs-comment">// to cast as a Person</span>
    <span class="hljs-keyword">const</span> person = personMaybe <span class="hljs-keyword">as</span> Person</code></span></pre>


<p class="wp-block-paragraph">However, while type narrowing to help the compiler is powerful, it&#8217;s also fraught with foot guns. We&#8217;ll see how we fix that with schemas.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2026/06/type-driven-development-unknown-vs-any.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
