Skip to content

Commit

Permalink
update some links, add promo blurb to type predicate post
Browse files Browse the repository at this point in the history
  • Loading branch information
danvk committed Apr 30, 2024
1 parent 95baa48 commit 37dd736
Show file tree
Hide file tree
Showing 7 changed files with 16 additions and 15 deletions.
2 changes: 1 addition & 1 deletion 2022/12/25/christmas/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ <h2>All I Want for Christmas Is… These Seven TypeScript Improvements</h2>
</time>
</div>
<div class="entry-content">
<p><a target="_blank" rel="noopener" href="https://freesvg.org/vector-clip-art-of-cartoon-presents-under-christmas-tree" onclick="return trackOutboundLink('all i want for christmas is these seven typescript improvements', 'https://freesvg.org/vector-clip-art-of-cartoon-presents-under-christmas-tree', event);"><img src="https://effectivetypescript.com/images/christmas-tree.png" width="200" height="200" style="float: right" alt="Christmas tree with presents"></a> It&#39;s Christmastime and I&#39;ve been happily working through this year&#39;s <a target="_blank" rel="noopener" href="https://adventofcode.com" onclick="return trackOutboundLink('all i want for christmas is these seven typescript improvements', 'https://adventofcode.com', event);">Advent of Code</a> in Deno (look forward to a blog post in the new year). What with all the presents, it&#39;s a good time to think about what we&#39;d most like to see from TypeScript in the new year. Here are my top seven feature requests for 2023. Yes, that&#39;s a lot, but really I&#39;d be thrilled with just one or two. Pretty please?</p>
<p><a target="_blank" rel="noopener" href="https://freesvg.org/vector-clip-art-of-cartoon-presents-under-christmas-tree" onclick="return trackOutboundLink('all i want for christmas is these seven typescript improvements', 'https://freesvg.org/vector-clip-art-of-cartoon-presents-under-christmas-tree', event);"><img src="https://effectivetypescript.com/images/christmas-tree.png" width="200" height="200" style="float: right" alt="Christmas tree with presents"></a> It&#39;s Christmastime and I&#39;ve been happily working through this year&#39;s <a target="_blank" rel="noopener" href="https://adventofcode.com" onclick="return trackOutboundLink('all i want for christmas is these seven typescript improvements', 'https://adventofcode.com', event);">Advent of Code</a> in Deno (look forward to a <a href="https://effectivetypescript.com/2023/04/27/aoc2022/">blog post</a> in the new year). What with all the presents, it&#39;s a good time to think about what we&#39;d most like to see from TypeScript in the new year. Here are my top seven feature requests for 2023. Yes, that&#39;s a lot, but really I&#39;d be thrilled with just one or two. Pretty please?</p>
<h2 id="A-faster-language-service"><a href="#A-faster-language-service" class="headerlink" title="A faster language service"></a>A faster language service</h2><p>When you install TypeScript, you get two executables:</p>
<ul>
<li><code>tsc</code>, which checks your code for type errors and converts it to executable JavaScript</li>
Expand Down
9 changes: 5 additions & 4 deletions 2024/04/16/inferring-a-type-predicate/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ <h2>The Making of a TypeScript Feature: Inferring Type Predicates</h2>
</time>
</div>
<div class="entry-content">
<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('the making of a typescript feature inferring type predicates', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting the PR merged, and what I&#39;ve learned along the way.</p>
<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('the making of a typescript feature inferring type predicates', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('the making of a typescript feature inferring type predicates', 'https://github.com/microsoft/TypeScript/pull/57465', event);">the PR</a> merged, and what I&#39;ve learned along the way.</p>
<p>This is not a short read, but it will give you a good sense of what it&#39;s like to become a TypeScript contributor and develop a new feature.</p>
<span id="more"></span>

<p>If you&#39;re new to the <em>Effective TypeScript</em> blog, consider <a href="https://effectivetypescript.com/mail/">subscribing</a> or buying a copy of <a target="_blank" rel="noopener" href="https://amzn.to/3UjPrsK" onclick="return trackOutboundLink('the making of a typescript feature inferring type predicates', 'https://amzn.to/3UjPrsK', event);">the book</a>. You can find a list of all the posts on this blog <a href="https://effectivetypescript.com/all-posts/">here</a>.</p>
<h2 id="What-is-Type-Predicate-Inference"><a href="#What-is-Type-Predicate-Inference" class="headerlink" title="What is Type Predicate Inference?"></a>What is Type Predicate Inference?</h2><p>Before we dive into the backstory, let&#39;s take a quick look at the feature I added. If you write code like this:</p>
<figure class="highlight ts"><table><tr><td class="code"><pre><code class="hljs ts"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumber</span>(<span class="hljs-params">data: unknown</span>) </span>&#123;<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">typeof</span> data === <span class="hljs-string">&#x27;number&#x27;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

Expand All @@ -113,15 +114,15 @@ <h2 id="Why-contribute-to-TypeScript"><a href="#Why-contribute-to-TypeScript" cl
<p>I&#39;ve been using TypeScript since 2016. I&#39;ve been <a target="_blank" rel="noopener" href="https://danvdk.medium.com/a-typed-pluck-exploring-typescript-2-1s-mapped-types-c15f72bf4ca8" onclick="return trackOutboundLink('why contribute to typescript', 'https://danvdk.medium.com/a-typed-pluck-exploring-typescript-2-1s-mapped-types-c15f72bf4ca8', event);">writing about it</a> <a target="_blank" rel="noopener" href="https://danvdk.medium.com/a-typed-chain-exploring-the-limits-of-typescript-b50153be53d8" onclick="return trackOutboundLink('why contribute to typescript', 'https://danvdk.medium.com/a-typed-chain-exploring-the-limits-of-typescript-b50153be53d8', event);">almost as long</a>. But I&#39;d never contributed code to it. This felt like a gap in my understanding of TypeScript and its ecosystem. Like most TS users, I have a <a href="https://effectivetypescript.com/2022/12/25/christmas/">long list</a> of features I&#39;d like to see added to the language, and I thought learning about compiler internals would help me understand which of those features were feasible and which weren&#39;t.</p>
<p>At the start of this year, I signed up for a 12-week batch at <a target="_blank" rel="noopener" href="https://www.recurse.com/" onclick="return trackOutboundLink('why contribute to typescript', 'https://www.recurse.com/', event);">Recurse Center</a>, a &quot;writer&#39;s retreat for programmers.&quot; You apply with a project in mind, and mine was to contribute to TypeScript. RC provided an encouraging structure and the space for me to make this leap.</p>
<h2 id="Hopes-and-Fears"><a href="#Hopes-and-Fears" class="headerlink" title="Hopes and Fears"></a>Hopes and Fears</h2><p>I hoped that I&#39;d build a stronger intuition for how TypeScript works internally and maybe have some insights along the way. If I was lucky, maybe I&#39;d be able to say I was a TypeScript contributor and make some improvements to the language.</p>
<p>My biggest fear was that I&#39;d put a lot of work into a PR only to see it stall. There are some <a href="ttps://github.com/microsoft/TypeScript/pull/38839#issuecomment-1160929515">notorious examples</a> of this, most famously the <a target="_blank" rel="noopener" href="https://twitter.com/JoshuaKGoldberg/status/1481654056422567944?lang=en" onclick="return trackOutboundLink('hopes and fears', 'https://twitter.com/JoshuaKGoldberg/status/1481654056422567944?lang=en', event);">cake-driven development incident</a>. I knew the real goal was to learn more about TypeScript. But I did hope to get a change accepted.</p>
<p>My biggest fear was that I&#39;d put a lot of work into a PR only to see it stall. There are some <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/38839#issuecomment-1160929515" onclick="return trackOutboundLink('hopes and fears', 'https://github.com/microsoft/TypeScript/pull/38839#issuecomment-1160929515', event);">notorious examples</a> of this, most famously the <a target="_blank" rel="noopener" href="https://twitter.com/JoshuaKGoldberg/status/1481654056422567944?lang=en" onclick="return trackOutboundLink('hopes and fears', 'https://twitter.com/JoshuaKGoldberg/status/1481654056422567944?lang=en', event);">cake-driven development incident</a>. I knew the real goal was to learn more about TypeScript. But I did hope to get a change accepted.</p>
<h2 id="Finding-a-first-issue"><a href="#Finding-a-first-issue" class="headerlink" title="Finding a first issue"></a>Finding a first issue</h2><!-- 2024-01-12 to 01-26 -->

<p><em>Mid- to Late-January 2024</em></p>
<p>Before trying to implement something substantial, I thought I&#39;d start by fixing a trivial bug. This would help me get familiar with the compiler and the development process. This is exactly how the TypeScript docs suggest you get started as a contributor.</p>
<p>Finding a &quot;good first issue&quot; proved harder than I&#39;d expected. Most of the small, newly-filed issues get fixed quickly by one or two experienced community members. From a community perspective, this is great: if you file a bug and it&#39;s accepted, it&#39;s likely to get fixed. But for a new contributor this isn&#39;t good: I was unlikely to win any races to fix an issue.</p>
<p>There&#39;s a <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/labels/Good%20First%20Issue" onclick="return trackOutboundLink('finding a first issue', 'https://github.com/microsoft/TypeScript/labels/Good%20First%20Issue', event);">good first issue</a> label, but this proved to be a bit of a joke. My <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/issues/29707" onclick="return trackOutboundLink('finding a first issue', 'https://github.com/microsoft/TypeScript/issues/29707', event);">favorite issue</a> in this category was discussed by three of the top contributors to TypeScript, who decided it was impossible or not worth doing. But it&#39;s still got that &quot;good first issue&quot; label!</p>
<p>Eventually I found <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/issues/53182" onclick="return trackOutboundLink('finding a first issue', 'https://github.com/microsoft/TypeScript/issues/53182', event);">#53182</a>, which involved numeric separators (<code>1_234</code>) not getting preserved in JS emit. This seemed low stakes and, as an added bonus, I&#39;m a fan of the <a target="_blank" rel="noopener" href="https://macwright.com/" onclick="return trackOutboundLink('finding a first issue', 'https://macwright.com/', event);">developer</a> who filed it.</p>
<p>The <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57144" onclick="return trackOutboundLink('finding a first issue', 'https://github.com/microsoft/TypeScript/pull/57144', event);">fix</a> was a one-liner, just like you&#39;d expect, but I learned a lot about how TypeScript works along the way. TypeScript&#39;s code structure defies many best practices. All the code for type checking is in a single file, <code>checker.ts</code>, that&#39;s over 50,000 lines of code. And these are meaty lines since there&#39;s no set line width and relatively few comments. It also makes extensive use of numeric enums, a feature I discourage in <a target="_blank" rel="noopener" href="https://amzn.to/3HIrQN6" onclick="return trackOutboundLink('finding a first issue', 'https://amzn.to/3HIrQN6', event);">Effective TypeScript</a>.</p>
<p>The <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57144" onclick="return trackOutboundLink('finding a first issue', 'https://github.com/microsoft/TypeScript/pull/57144', event);">fix</a> was a one-liner, just like you&#39;d expect, but I learned a lot about how TypeScript works along the way. TypeScript&#39;s code structure defies many best practices. All the code for type checking is in a single file, <code>checker.ts</code>, that&#39;s over 50,000 lines of code. And these are meaty lines since there&#39;s no set line width and relatively few comments. It also makes extensive use of numeric enums, a feature I discourage in <a target="_blank" rel="noopener" href="https://amzn.to/3UjPrsK" onclick="return trackOutboundLink('finding a first issue', 'https://amzn.to/3UjPrsK', event);">Effective TypeScript</a>.</p>
<p>That being said, there are some impressive parts of the tooling. Visual debugging (F5) works great in VS Code and is an excellent way to learn what the compiler is doing. There are relatively few unit tests, but there&#39;s an enormous collection of &quot;baselines,&quot; a sort of end-to-end test that snapshots the types and errors for a code sample. There are over 18,000 of these, but TypeScript is able to run all of them on my laptop in just a few minutes.</p>
<p>After a few weeks, my PR was merged and released as part of TypeScript 5.4. I was officially a TypeScript contributor!</p>
<h2 id="A-meatier-second-issue"><a href="#A-meatier-second-issue" class="headerlink" title="A meatier second issue"></a>A meatier second issue</h2><!-- Starting ~2024-01-26; first commit on infer-guard is 2024-02-02 -->
Expand Down Expand Up @@ -283,7 +284,7 @@ <h2 id="More-performance"><a href="#More-performance" class="headerlink" title="

<h2 id="A-productive-prod"><a href="#A-productive-prod" class="headerlink" title="A productive prod"></a>A productive prod</h2><p><em>March 12, 2024</em></p>
<p>At this point the PR stalled for around a week. I wanted to keep things moving along, but I also didn&#39;t want to be that person posting &quot;any updates?&quot; comments. I&#39;ve been on both sides of this. Those comments are rarely helpful. Presumably everyone wants the PR to make progress, there are just other priorities.</p>
<p>But in this case, there was an opportunity for a more constructive nudge. I had a draft of the <a target="_blank" rel="noopener" href="https://www.amazon.com/Effective-Typescript-Specific-Ways-Improve/dp/1098155068/" onclick="return trackOutboundLink('a productive prod', 'https://www.amazon.com/Effective-Typescript-Specific-Ways-Improve/dp/1098155068/', event);">second edition</a> of <em>Effective TypeScript</em> due on March 15th. One of the new items was &quot;Know how to filter null values from lists.&quot; If my PR went in, that item would be completely unsalvageable, and the best course of action would be to delete it completely.</p>
<p>But in this case, there was an opportunity for a more constructive nudge. I had a draft of the <a target="_blank" rel="noopener" href="https://amzn.to/3UjPrsK" onclick="return trackOutboundLink('a productive prod', 'https://amzn.to/3UjPrsK', event);">second edition</a> of <em>Effective TypeScript</em> due on March 15th. One of the new items was &quot;Know how to filter null values from lists.&quot; If my PR went in, that item would be completely unsalvageable, and the best course of action would be to delete it completely.</p>
<p>Ryan Cavanaugh was a reviewer for the book, so I asked him what he thought the odds of my PR being merged were. If they were greater than 50/50, I should just delete the item.</p>
<p>Ryan said that Anders was &quot;super stoked&quot; on the PR and he thought it would go in for 5.5. Wow! Even better, he took the hint and reassigned the PR to Anders, who immediately approved it. Amazing! Ryan said he&#39;d ping the team for a last round of reviews.</p>
<h2 id="The-final-review"><a href="#The-final-review" class="headerlink" title="The final review"></a>The final review</h2><p><em>March 13–15, 2024</em></p>
Expand Down
2 changes: 1 addition & 1 deletion archives/2024/04/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ <h3 class="entry-title">

<div class="entry-content">

<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting the PR merged, and what I&#39;ve learned along the way.</p>
<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">the PR</a> merged, and what I&#39;ve learned along the way.</p>
<p>This is not a short read, but it will give you a good sense of what it&#39;s like to become a TypeScript contributor and develop a new feature.</p>
<a class="read-more" href="/2024/04/16/inferring-a-type-predicate/">Continue&nbsp;reading&nbsp;&raquo;</a>

Expand Down
2 changes: 1 addition & 1 deletion archives/2024/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ <h3 class="entry-title">

<div class="entry-content">

<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting the PR merged, and what I&#39;ve learned along the way.</p>
<p>Over the past few months I became a TypeScript contributor and implemented a new feature, <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">type predicate inference</a>, that should be one of the headliners for TypeScript 5.5. This post tells the story of how that happened: why I wanted to contribute to TypeScript, the journey to implementing the feature and getting <a target="_blank" rel="noopener" href="https://github.com/microsoft/TypeScript/pull/57465" onclick="return trackOutboundLink('recent blog posts', 'https://github.com/microsoft/TypeScript/pull/57465', event);">the PR</a> merged, and what I&#39;ve learned along the way.</p>
<p>This is not a short read, but it will give you a good sense of what it&#39;s like to become a TypeScript contributor and develop a new feature.</p>
<a class="read-more" href="/2024/04/16/inferring-a-type-predicate/">Continue&nbsp;reading&nbsp;&raquo;</a>

Expand Down
Loading

0 comments on commit 37dd736

Please sign in to comment.