<?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: Daniel Bolívar</title>
    <description>The latest articles on DEV Community by Daniel Bolívar (@ddanielbee).</description>
    <link>https://dev.to/ddanielbee</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%2F47102%2Fbb49b39b-17d3-4b47-82f3-0b24e12277fb.jpg</url>
      <title>DEV Community: Daniel Bolívar</title>
      <link>https://dev.to/ddanielbee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ddanielbee"/>
    <language>en</language>
    <item>
      <title>Understanding React Children types</title>
      <dc:creator>Daniel Bolívar</dc:creator>
      <pubDate>Wed, 01 Sep 2021 15:36:22 +0000</pubDate>
      <link>https://dev.to/ddanielbee/understanding-react-children-types-2bh4</link>
      <guid>https://dev.to/ddanielbee/understanding-react-children-types-2bh4</guid>
      <description>&lt;p&gt;So, here's the deal. I'm not a big fan of React's children property. Don't get me wrong, I know why it's good. I know why it's useful and I also very much know that I don't like to use it much when I'm writing React components. I've seen it used mostly to create stateless wrappers that only add an extra, non-semantic &lt;code&gt;div&lt;/code&gt; and a CSS class, resulting in the ever wonderful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeaderWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;HeaderWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That renders into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"header-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Something&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This is a simplified example... what I'm trying to say is that my experience with components that make explicit use of children is bad. And I'm biased.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But when &lt;a href="https://twitter.com/PipeSalazar"&gt;Felipe&lt;/a&gt; showed me his idea for a component that used children, not just for adding a wrapper, but for making decisions on which child to render based on parent props, I realized I should probably put my bias aside. And this is when we asked ourselves the question to end all questions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I constraint the parent component's children type, to be of a single component type?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And thus, we set out on a mighty journey towards type enlightenment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting out
&lt;/h2&gt;

&lt;p&gt;We started where every journey starts. Five steps further than we should have, by trying to immediately run something on a &lt;code&gt;.tsx&lt;/code&gt; file that looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;a&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;b&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ParentComponentProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChildComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;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;ParentComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seemed like we had triumphed! We had no red squiggly lines on our code and the idea looked sound. So, we tried it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ParentComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works fine. But we needed to make sure that Typescript would yell at us if we tried to give a child that wasn't a &lt;code&gt;ChildComponent&lt;/code&gt;. And we hit a concrete wall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;I&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m not a ChildComponent, this shouldn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="nx"&gt;work&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ParentComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Narrator: It did work&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it worked (when it shouldn't have)
&lt;/h2&gt;

&lt;p&gt;There's a very simple reason why our component did not yell at us when we passed it a child that didn't fulfill the constrain we thought we had in place. And it has to do with the type of a &lt;code&gt;FunctionComponent&lt;/code&gt; in React.&lt;/p&gt;

&lt;p&gt;Here we go:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FunctionComponent&lt;/code&gt; is:&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;FunctionComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;propTypes&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;WeakValidationMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;contextTypes&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ValidationMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&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;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're interested in the first line of that interface definition, the one where the function that takes &lt;code&gt;props&lt;/code&gt; is defined. So, we dive a bit deeper into what &lt;code&gt;PropsWithChildren&amp;lt;P&amp;gt;&lt;/code&gt; is and find this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&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 it. This is the &lt;strong&gt;aha&lt;/strong&gt; moment. Or maybe it should've been, if we already knew how Typescript handles these cases, which we didn't at the time.&lt;/p&gt;

&lt;p&gt;What we have here is a &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces"&gt;type extended by an intersection&lt;/a&gt;, where both sides of the intersection have differing definitions of a property with the same name. Remember, our &lt;code&gt;P&lt;/code&gt; in this case was:&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;ParentComponentProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how both the &lt;code&gt;P&lt;/code&gt; and the inline type &lt;code&gt;{ children?: ReactNode}&lt;/code&gt; have the &lt;code&gt;children&lt;/code&gt; property? And furthermore, they have different values!&lt;/p&gt;

&lt;p&gt;So, how does Typescript resolve extended types where this happens? Well, it does the only thing that makes sense. It creates an &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types"&gt;union type&lt;/a&gt; out of them. What comes out after all this is done is:&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;FinalParentComponentProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reactelement&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This is ReactNode btw:&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactChild&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactFragment&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactPortal&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// And this is ReactChild&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReactChild&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. &lt;code&gt;ReactElement&lt;/code&gt; is fulfilled by any JSX element, like our &lt;code&gt;&amp;lt;div&amp;gt;Not correct component&amp;lt;/div&amp;gt;&lt;/code&gt; intruder up there. And this makes sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  The React contract
&lt;/h2&gt;

&lt;p&gt;Apart from any internal React explanation (there is one, but now is not the place), at the type definitions perspective, this makes sense. React's component contract is that they will render the JSX passed into HTML. And HTML will let us pass &lt;code&gt;&amp;lt;div&amp;gt;s&lt;/code&gt; or anything else, inside anything really. Sure, sometimes it might yell at us for violating dom validations like a &lt;em&gt;button&lt;/em&gt; inside a &lt;em&gt;button&lt;/em&gt;, but it'll still let us do it. And so does React, letting us pass any JSX element as a child to any component that can take children. So, yeah, we learned that we can't do this at the type level. So, can we do it elsewhere?&lt;/p&gt;

&lt;h2&gt;
  
  
  The runtime solution
&lt;/h2&gt;

&lt;p&gt;Typescript can't do it. But this is JS, where everything is possible and the points don't matter. So, we can loop through the children and check their type. Then, blow everything up if it doesn't match what we wanted. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;child&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;ChildComponent&lt;/span&gt;&lt;span class="p"&gt;)&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="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Only ChildComponents allowed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this works... it's not ideal. We don't want our typed component to break at runtime because the person using it didn't know that it would break rules set in place by the framework itself. Let's not do that 😅.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that doesn't actually use children
&lt;/h2&gt;

&lt;p&gt;There's another option to keep things typesafe and kind of get the end result we want... only it skips the usage of the children prop entirely. You probably already have an idea where I'm going with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ParentComponentProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;childrenProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;childrenProps&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;childrenProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;props&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, our component will only render &lt;code&gt;ChildComponents&lt;/code&gt; and it will be typesafe at usage. But it bypasses the whole idea about using &lt;code&gt;children&lt;/code&gt; 🙈.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other options?
&lt;/h2&gt;

&lt;p&gt;There's a few other things that work. Instead of throwing an error, we could ignore that element and only render the ones that fulfill the type constraint. Or, we could assert on the existence of a prop in the child instead of the type, to keep it a bit less strict while also making sure that the children contain the data we need to render them correctly. There's a lot we can do... doesn't mean we should do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;I still believe that &lt;code&gt;children&lt;/code&gt; are best reserved for libraries that concern themselves with wrapping components in order to enhance them. Think, CSS in JS, or stuff involving the Context api that wants to wrap things in &lt;code&gt;Providers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Does it look cool to do stuff like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second Child&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ParentComponent&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sure it does. And it has its pros, like every child having their own children and making the &lt;code&gt;ParentComponent&lt;/code&gt;'s api very flexible. But the cost for this, is runtime behaviour that will need to be explained in out of code documentation and maintained fresh in the minds of any developer using this component.&lt;/p&gt;

&lt;p&gt;Given that writing good docs is one of the hardest tasks in software, I'd say that cost is too high for &lt;em&gt;most&lt;/em&gt; cases.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shoutouts to &lt;a href="https://twitter.com/PipeSalazar"&gt;Felipe&lt;/a&gt; who consistenly comes up with interesting ideas like this one. They usually end up in both of us learning a lot (and still disagreeing about the children property).&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Talking bout my Generator</title>
      <dc:creator>Daniel Bolívar</dc:creator>
      <pubDate>Fri, 11 Sep 2020 07:39:50 +0000</pubDate>
      <link>https://dev.to/ddanielbee/talking-bout-my-generator-2jfl</link>
      <guid>https://dev.to/ddanielbee/talking-bout-my-generator-2jfl</guid>
      <description>&lt;p&gt;The year is 2020, the world feels like it's on fire (both literally in some places and figuratively in most others) and you decide to use your massive amount of indoor time to revamp that good ol' personal website you built last year. So, what do you do?&lt;/p&gt;

&lt;h2&gt;
  
  
  The options
&lt;/h2&gt;

&lt;p&gt;If you're anything like me, your personal website is a blog created by a Static Site Generator (SSG from now on) and it has gone through some identity crises. In my case, each of these moments has been marked by my decision to switch the technology powering the site. Here's how that went:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hello world version used &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; because it was between Jekyll and Hugo, and I already had had bad experiences with Jekyll. Seemed like a pretty solid choice at the time.&lt;/li&gt;
&lt;li&gt;Last year, I switched to &lt;a href="https://www.gatsbyjs.com/"&gt;Gatbsy&lt;/a&gt;, buying into the hype and their promises of a &lt;em&gt;blazing fast&lt;/em&gt; website. Also, it was React under the hood, and I had been working with React for a while at that point. Again, seemed like the clear winning idea.&lt;/li&gt;
&lt;li&gt;The current version uses &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt; and the decision this time was more community induced. I follow &lt;a href="https://twitter.com/zachleat"&gt;Zach&lt;/a&gt; on twitter and had been reading more and more about Eleventy, and it seemed intuitive and all about the basics of the web, so I went with it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The experiences
&lt;/h2&gt;

&lt;p&gt;Each SSG provides focuses on different things. They also have different underlying technologies, so they'll naturally feel really different to use. Here's my personal experience with each of them:&lt;/p&gt;

&lt;h3&gt;
  
  
  Hugo
&lt;/h3&gt;

&lt;p&gt;My relationship with Hugo was pretty shallow, I must say. I don't write Go, so I found a theme online for a blog that seemed to fit my needs and went with it. I think the only customization I did was change the navigation items and create a category. It did its job, but having to learn a whole new programming language just to go deeper into customizing stuff was too big a price to pay for me, at that point in time, so I decided to switch to:&lt;/p&gt;

&lt;h3&gt;
  
  
  Gatsby
&lt;/h3&gt;

&lt;p&gt;Ah, Gatsby. The day I started, I decided to go the simplest way I could think: find a blog theme I liked, install it and dump all my old content into the new system. After adding the theme, the build started failing. 30 minutes later, 5 different github issues and some of my own tinkering, I found out that one of the dependencies that the theme used needed to be updated to be compatible with the changes on another. Just another day in the JS office. Also, it didn't build with the node version I used by default (12 I think) and I needed to downgrade to &lt;strong&gt;v10&lt;/strong&gt; to build the site. As stubborn as I am, I'm also very lazy and when &lt;em&gt;out of the box&lt;/em&gt; things don't work, well, out of the godforsaken box, I can't help but generate animosity towards the thing. It also happened with Create React App when I tried to use it on the one day they had published a breaking bug. Maybe I'm lucky like that.&lt;/p&gt;

&lt;p&gt;Back go Gatsby. After all the issues had been ironed out, copying the content over and changing the frontmatter to fit the theme's structure was a bit easier. And then I decided to add pagination. Looking back at that commit, it seems rather straightforward, but boy oh boy how I suffered with it. It's partly my fault, for assuming tinkering with a premade theme would be easy. But the combination of the &lt;code&gt;createPages&lt;/code&gt; function and having to learn more Graphql turned what should've been a fun experience, into a grueling slog. And by the end of it, I was so put off that I stopped doing stuff on my page. Forever. Until last week.&lt;/p&gt;

&lt;p&gt;Now, it's clear that Gatsby wasn't for me. It's probably more powerful than I needed it to be, but it's also true that there is a lot of complexity for very small output. I mean, I only wanted some HTML pages generated out of markdown, and pagination on the post list. For that I was using&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQl&lt;/li&gt;
&lt;li&gt;JSX&lt;/li&gt;
&lt;li&gt;18 different Gatsby plugins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And at the end of it, I had a website. Sure, it worked well, but it still wasn't getting me 100's on Lighthouse's performance report. The reason being that you still ship a javascript bundle whenever you use Gatsby, regardless of how static you make your website. The main reason for this, is to have the SPA like routing experience, where it seems like the browser never reloads. Don't get me wrong, that's nice and all, but what does it matter when I'm reloading for a simple HTML document?&lt;/p&gt;

&lt;h3&gt;
  
  
  Eleventy
&lt;/h3&gt;

&lt;p&gt;Here's Eleventy's one promise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Eleventy is a &lt;strong&gt;simpler&lt;/strong&gt; static site generator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The word &lt;strong&gt;simpler&lt;/strong&gt; is important. You'll notice the distinct lack of buzzwords like &lt;em&gt;blazing fast&lt;/em&gt; or &lt;em&gt;modern&lt;/em&gt;. No, it's just a static site generator. And it's a simple one. And that, my dear reader, it is.&lt;/p&gt;

&lt;p&gt;I went a different way with Eleventy. Because of how much I had already heard about it, I was beyond curious to dig in. I skimmed through the docs to get an idea of the concepts. And then, fate showed its hand: there was a huge twitter thread on how bad Gatsby (the company) was at treating their employees. A couple weeks before, &lt;a href="https://twitter.com/hankchizljaw"&gt;Andy Bell&lt;/a&gt; had just released his course on Eleventy, &lt;a href="https://piccalil.li/course/learn-eleventy-from-scratch/"&gt;Learn Eleventy From Scratch&lt;/a&gt; and ran a very timely sale to help people get off the Gatsby train. The path forward was pretty clear for me: buy and go through the course and swap out Gatsby for Eleventy when I was done. And so I did.&lt;/p&gt;

&lt;p&gt;Doing stuff with Eleventy is a joyful experience. Most topics in Eleventy work as you expect them to. Collections, Layouts, Markdown, and Frontmatter are pretty straightforward, but there are a couple of things one needs to learn in order to elevate Eleventy to its full potential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A templating engine supported (I used Nunjucks).&lt;/li&gt;
&lt;li&gt;How the aptly named &lt;a href="https://www.11ty.dev/docs/data-cascade/"&gt;Data Cascade&lt;/a&gt; works.&lt;/li&gt;
&lt;li&gt;And &lt;a href="https://www.11ty.dev/docs/pagination/"&gt;pagination&lt;/a&gt;. Probably.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the pieces fall into place, Eleventy starts to shine. It really is &lt;strong&gt;simple&lt;/strong&gt; in the best way possible. In the same time, it took me to add pagination to my Gatsby version, I managed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Figure out how to have a &lt;a href="https://dabolivar.com/not-an-actual-page"&gt;404 page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a conditional link on the homepage inviting people to see all the posts when there are more than the displayed posts (5 in my case) in the collection.&lt;/li&gt;
&lt;li&gt;Create a custom pagination like structure to have &lt;em&gt;next&lt;/em&gt; &amp;amp; &lt;em&gt;previous&lt;/em&gt; posts on an individual post.&lt;/li&gt;
&lt;li&gt;Add a super simple Service Worker to cache pages for offline use, using an &lt;a href="https://github.com/okitavera/eleventy-plugin-pwa"&gt;eleventy plugin&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I attribute a big chunk of my success with Eleventy to Andy's &lt;a href="https://piccalil.li/course/learn-eleventy-from-scratch/"&gt;amazing course&lt;/a&gt; (seriously, go buy it, it's great). But there is no mistaking the fact that the people behind Eleventy have done a marvelous job at creating a great developer experience.&lt;/p&gt;

&lt;p&gt;Oh, and best of all, even though there's some Javascript powering some of the feature I built, other than the Service Worker register, the website contains no Javascript. Sure, it reloads with every click, but it takes a second on a Moto4G with a regular 3G connection to load. Who needs an SPA routing mechanism at that point?&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I love Eleventy. It's rekindled my love of the web, HTML and CSS. Sure, I'm not learning the newest, greatest, most hype-worthy technology like I would if I invested in Gatsby... but maybe that's a good thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S:&lt;/strong&gt; The only one negative thing about Eleventy is that using Typescript instead of plain JS isn't really straightforward. It's possible but needs some tinkering and the current methods make the experience a lot clunkier. Not a deal-breaker by any means, but it would be pretty awesome to have that out of the box.&lt;/p&gt;

</description>
      <category>eleventy</category>
      <category>ssg</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
