<?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>Forem: Luis Gustavo Macedo</title>
    <description>The latest articles on Forem by Luis Gustavo Macedo (@luisgustavom1).</description>
    <link>https://forem.com/luisgustavom1</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%2F1007541%2F0cd64a9e-eb62-475c-b4a4-20d927ee6ae8.jpeg</url>
      <title>Forem: Luis Gustavo Macedo</title>
      <link>https://forem.com/luisgustavom1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/luisgustavom1"/>
    <language>en</language>
    <item>
      <title>Typescript - Union types e type guards</title>
      <dc:creator>Luis Gustavo Macedo</dc:creator>
      <pubDate>Mon, 17 Jul 2023 14:45:16 +0000</pubDate>
      <link>https://forem.com/luisgustavom1/typescript-union-types-and-type-guards-14gh</link>
      <guid>https://forem.com/luisgustavom1/typescript-union-types-and-type-guards-14gh</guid>
      <description>&lt;p&gt;Salve galera!&lt;/p&gt;

&lt;p&gt;Hoje quero compartilhar mais um pouco sobre typescript, especificamente algumas técnicas utilizando &lt;code&gt;Union Types&lt;/code&gt; e &lt;code&gt;type guards&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vou mostrar como você pode melhorar seu código typescript pra deixá-lo mais legível, e bem documentado. &lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Union types
&lt;/h2&gt;

&lt;p&gt;Um &lt;code&gt;Union types&lt;/code&gt; é um tipo formado por outros tipos, onde pode assumir qualquer um daqueles possíveis valores. &lt;/p&gt;

&lt;p&gt;Alguns exemplos&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;NumberOrString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failure&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// React useState, can receive a value or a function as parameter to serve as initial value. &lt;/span&gt;
&lt;span class="c1"&gt;// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a03856975a17eba524739676affbf70ac4078176/types/react/v17/index.d.ts#L920&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&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;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;S&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="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SetStateAction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2 - Typeguard
&lt;/h2&gt;

&lt;p&gt;Já o &lt;code&gt;typeguard&lt;/code&gt; é uma forma de dizer para o typescript, por meio de algum fluxo de controle &lt;code&gt;if/else, loops, ternários e etc&lt;/code&gt;, refinar - chamamos de &lt;strong&gt;&lt;em&gt;narrow&lt;/em&gt;&lt;/strong&gt; - um determinado tipo para um tipo mais específico em algum escopo definido. &lt;/p&gt;

&lt;p&gt;Dessa forma, conseguimos inferir que em algum ponto do código, um tipo pode assumir um tipo específico. &lt;/p&gt;

&lt;p&gt;Pra quem quiser ler mais sobre &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html"&gt;&lt;code&gt;narrowing e typeguards&lt;/code&gt;&lt;/a&gt;, lá tem bastante exemplo e uma explicação completa.&lt;/p&gt;

&lt;p&gt;Podemos fazer o &lt;code&gt;narrowing&lt;/code&gt; apenas com operações javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// using switch&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OrderCompleted&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;OrderProcessing&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;OrderReady&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;completed&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deliveryAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Narrow to OrderCompleted &lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;processing&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expectDeliveryAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Narrow to OrderProcessing &lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ready&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Narrow to OrderReady &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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgPJQCbQEJwM4oDeAUMsiHALYQBcyeYUoA5qcgA5QD2GArgmACSGOgyYhWAX2TFioSLEQp0WKAGEuldgBsIkDMggAPSCAx40mHPiJsGcMLzx0ARAk069EDC4A0bLG1gADdoAE8AQTA6ABEHCH9JWXloeCRLVQAFbiQ8PBZDEwgzCxVrAmQSMntHZ2QXTi5c-Ik-NmN2CAEYiCDQqEjo5DjIYiS5cFSlDOgAJQg4DDDC03MZqFwKqvowBydXKAWllzHZMDDO9eQAXnWNLV19ZAAfdeymiDyC17KoecWwgBuWQwXggATALggDg5T54X4ACi4VigdF+AEpKnYAO7AMAIAAWyCRKIAdDUnJjtmQEDZ6u4Hl4fHRqWRkO4QHguLpSdouMwSapSYEQuEopiAPQS5AAOTgUG42OQYC4dw8j28MjZbMOjigIGB2qS2tpFQasK+rRZbBNUK5PL5AuRQo6XTAPT6YrAkulcoVXCVKreFpazC12uQut4+sNbONbNNKBchwBLmtEfZdu5EF5-MF0FJjT4AmEPtl8sVytVv3+S3DZHjSUkQA"&gt;TS Playground&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// using in operator&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;Fish&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;swim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Fish&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;walk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Narrow to Dog&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;swim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Narrow to Fish&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// using typeof&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&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="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// So in this scope you ensure that function exists&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;&lt;a href="https://www.typescriptlang.org/play?#code/PTAEFcGcEsDsHNR1AewA4FMBOBDALilgFBx7YBmOAxhqACIqIDeRoboA7jgDYDWAXKAAUASlABeAHygAbimgATANxEAvkRKwyWSjVAAxaJAAWoFu1CQO0ALaDRE6XMUr1RPAE9MoAIKxbPBL0jKAAPgZGxipE5OCwVHjQKLCgNigyGEI4-jY8gn4B3GLm7NDkwgBEXHwVSCnZhcWsFuwNudwAdNW8okqgIHXk2KB4xvgjXrRGoDjB8M0toFgYeOBYsCoWbhZtPB1Wtr39YHBDWCNjeBPe07OGJmoaRANQcIiemCjkMXEJSSloLAoGxGTJUHjcABG1F4AH57GIpLJ5AomhYBh1MQskOUhB8MF9QODuFCYaAAITicSgCpxBQYchwDAKCpoxZEiHQqg9ER9AYAZRQdQu00gVHQtA8KHAoAwsEga1oo3GsXiiWSsoAHkY8JBsepVEA"&gt;Ts Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tudo que fizemos até agora foi apartir do fluxo do código usar operações javascript para ajudar o typescript a fazer o &lt;code&gt;narrowing&lt;/code&gt; e inferir tipos mais específicos.&lt;/p&gt;

&lt;p&gt;Agora, se quisermos fazer nossas próprias validações, sem usar explicitamente operações javascript como &lt;code&gt;typeof&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, &lt;code&gt;instanceof&lt;/code&gt; e outros, no fluxo do código, mas sim encapsular toda a lógica de validação em uma função, como um parser ou algo do tipo. Pra isso podemos usar o &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates"&gt;&lt;code&gt;type predicates&lt;/code&gt;&lt;/a&gt; do typescript.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 - Type Predicates
&lt;/h2&gt;

&lt;p&gt;Um exemplo muito comum é quando fazemos uma chamada pra API e apenas inferimos o tipo do retorno, mas o que garante pra gente que a API mandou o objeto correto?&lt;/p&gt;

&lt;p&gt;O problema&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;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;email&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;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&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;T&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;endPoint&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getUser&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// We assume that the response payload actually sent the object with the type strictly equal to User&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;Podemos fazer uma função para garantir que o objeto &lt;code&gt;user&lt;/code&gt; é de fato do tipo &lt;code&gt;User&lt;/code&gt;.&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;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;email&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
        &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&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;T&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;endPoint&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getUser&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// We can pass the User as a generic here, however we have to remember to do the validation&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;isUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// With this type guard, we can be sure that the API response actually returned a User. &lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="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;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChkHIhwC2EAXMumFKAOYDc+hEJcwANpdbSI7gF9cuGAFcQCMMAD2IZMHQZoAClAAHUWEriA1iGkB3EAEpK6zfPRpMUAnkLIoEMKKhzlzBwTABPNRGkYeRANMGQAXkjkACJpACMAKwhJaOQAMjTkTy8AQhzzMIzsh2jiMlTQYND0tOLCaNZ2Dgq5AuzjLKFcABNkjjgnZARZamQ4NWBKAB4AFQA+ZQgQboAFaVAtKhp6DvC55BnhMQkpWWQ6ZyUoZQ77QmGQUdEbCLGJ5WiAemfoaOMGZCfT7IADqKAQcDkajg6CsYAAFigrmMrHBzktoMAEMhEU4ADQ4wwQABuWAMKHhcFJyDA0kcrFYcSwtOQ3TpCJQxLgHGA3TgpxA2WywCCqkUNmUPygxlugOBIOACJp8IUNL8KDoogG3QJ5KGkOQTKorhQCP5ypQAEEVgBJenoNQjFCIFzcjg+ekuNwQbpjazQAB0WS89xG0g4EADHGkdElNgDjU4-2DIaGYYjUZjccDZQg-zqBCcXpATAcQgEQA"&gt;Ts Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Porém ainda tem um problema aqui, veja no &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChkHIhwC2EAXMumFKAOYDc+hEJcwANpdbSI8wTgA3OGDhRuNekwC+uXDACuIBGGAB7EMmDoM0ABSgADorCVlAaxDqA7iACUlY6e3o0mKAWzIA9D+QAchAgABaKJMjQUOrIcACOisACyFAQYIpQWvrJhMhgAJ5GEOow2iAmYMgAvDXIAETqAEYAVhCqdcgAZJ3IOYQAhP3Old19BHXEZB2gZRVdnWP1rOwc01rDyfa9crgAJm0c4igImtSxRsCUADwAKgB8+sG7AArqoGZUUnxbVXfIN-IlCo1JpkHQ0nooPotnhcicQGdFB5qudgPo6j4kdA6vYGL5-ABBMAAS+QRnU+xI6jcRjg6HQ4mQMUhyBOVOQ4TBwWgwAQsQSwAANGT1FBiRFIFS3AkUBxWI0oIz9sh4AAvLBwZAiDjAXZwADnAGP1PJcsBSoZdB59FioPYYfjkABhdQRCD0lAFIpgxTiXbC+GYOiJKV5DWs6CQVWamWxFLu8nUTV65AE54ASWQyvgYBiqVzmXUig5ERZi0D6jlADoOOo6DaPFXlpxcb1cnDTpWIDW6w3oFXJhBcYt8xkQExcnIZEA"&gt;playground&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Suponha que estamos no final da sprint, e então surge uma urgência e temos que introduzir mais um campo no tipo &lt;code&gt;User&lt;/code&gt;, por exemplo, o campo &lt;code&gt;avatar&lt;/code&gt;. Nossa função &lt;code&gt;isUser&lt;/code&gt; não vai acusar nenhum erro por não estarmos verificando o campo &lt;code&gt;avatar&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Como a sprint está acabando e fizemos a alteração as pressas, esquecemos de alterar a função e nosso &lt;code&gt;isUser&lt;/code&gt; não está funcional, não cumpre com o que deveria, por que não valida se de fato o objeto é um &lt;code&gt;User&lt;/code&gt;. Então, bummm introduzimos um possível bug em produção. &lt;/p&gt;

&lt;p&gt;Podemos resolver isso mudando um pouco nossa função para ser um parser de fato, e deixar ela mais completa validando também o tipo de cada propriedade&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;function&lt;/span&gt; &lt;span class="nx"&gt;parseUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;User&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;hasUserProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasUserProperties&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Property 'avatar' is missing in type '{ email: string; name: string; }' but required in type 'User'.(2741)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Veja no &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChkHIhwC2EAXMumFKAOYDc+hEJcwANpdbSI8wTgA3OGDhRuNekwC+uXDACuIBGGAB7EMgAO4zBmgAKUNsVhKygNYh1AdxABKSgajIAPkUUcOOAcgSa1MjA6ADyAEYAVhCqyAC8yGAAntoQ6jDBIKZg8XEJAETqUTFg+cgAZOWZ2X7AGYYAhCER0aoOyFAQYIpQWiBeHEx+ASBBABZw6C4AClDqqVBqEOjxyH6EyPnEZGWg1WYV5euE+azsHLtaJmbyG3XIjRNTmFCz89BL6O2d3b2e3kMNiMgthkGdOAAaIikFAyVbXMCAwj3QzJVLpMFsTjIBp5TY8ej5b5dHp9AZMO71NFpDLbFC4goEvhEjokv79AG3Qg-Uk4THnKF05BwgD0IuQbwWyWQAHJhKJxDLgisSCF0PRMokUigZaDwVwqFI+AxoWRJLxGMKleEDp0AI6KYCdAAmmupspcMoAdIYAEwAdgALABGBy4OQKZSqDRXZ5GBEWEDWOyOSgI5VoF6+DY8v7phn-Djh+TOmIccQoYE5ODaYCUAA8ABUAHyGCAgZ3TdSgcyGi3tOLN5CN+RKFRqTTIOhdFyGdp4IGBHKKLMJGvAQz5EUr6BEk1cggokKzndQBzztYbRejdQcCBejjqOiGU9e-UOfdXwjA2-3x-P186Q-Y4CFzEAKUIOQZCAA"&gt;playground&lt;/a&gt;, agora se novas propriedades forem adicionadas nossa função irá acusar erro.&lt;/p&gt;

&lt;p&gt;Já temos algumas ótimas ferramentas pra fazer todo esse parser, como o &lt;a href="https://zod.dev/"&gt;zod&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - Extract Utility
&lt;/h2&gt;

&lt;p&gt;Pra finalizar, quero mostrar um utilitário muito poderoso que o typescript oferece quando trabalhamos com &lt;code&gt;union types&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por exemplo, se o &lt;code&gt;union&lt;/code&gt; for de uma biblioteca externa, e não temos acesso a cada possível valor de forma isolada. Podemos inferir o tipo específico usando o &lt;code&gt;Extract&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;Extract&lt;/code&gt; recebe dois genéricos, o primeiro é o &lt;code&gt;Union&lt;/code&gt; de fato e o segundo apenas a união que vai ser extraída.&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;Payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;paidAt&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="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;canceledAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PendingPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// { status: "pending" }&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PaidPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// { status: "paid", paidAt: string }&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CanceledPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// { status: "canceled", canceledAt: string } &lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;radius&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Square&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// { kind: "square"; size: number; } &lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// { kind: "circle"; radius: number; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBACghiAthAdsKBeKAoKeoA+UA3lAM7BzACuZAXFAESQoAmAligOaNQC+ufEVIUqtBszjtWjADRQwU1gEFgDCgCdOXfoLzDylGvSYBjOClMQANhBnzzlm3dXrgW7vxzZQkWKg5ueCRUdCwAUQAPdzhTYAAeYOQ0eREjcSYWQJ5+AD4AbigAeiKSQzETZgDtXgFfaHhpJNDMKCiYuMSEZOBU8uMJRWlaguLStIrBpTkFJVdDDx068GgAYQsrW1ZmtFb2jViEnd6y0QGzDecZPMKS0-TKx027Gaer+c1tL2wfFagAZQAFnA-FhiIIANacVgSMgAR2ocA0EEY+UEZHYAC8IAwUNREAAjCAaNF8QgkSHQiSmdgaUy2VGCA4cDJ4wnE0lo35+f4IpHQCLRA6dIEgiB9M4ZRjwxHIka3cZQKFsWF8uWFDHY3H4okk771KCrWn0gVtIWHeKiyASh7U40Mm5jMrKmFme0owrM9isnUc-hAA"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É isso, acho que assim da pra deixar o código mais explícito, legível e bem documentado.&lt;/p&gt;

&lt;p&gt;Referências:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html"&gt;https://www.typescriptlang.org/docs/handbook/advanced-types.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#typeof-type-guards"&gt;https://www.typescriptlang.org/docs/handbook/2/narrowing.html#typeof-type-guards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/noriste/keeping-typescript-type-guards-safe-and-up-to-date-a-simpler-solution-ja3"&gt;https://dev.to/noriste/keeping-typescript-type-guards-safe-and-up-to-date-a-simpler-solution-ja3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://levelup.gitconnected.com/typescript-keeping-type-guards-safe-and-up-to-date-2457d52bd722"&gt;https://levelup.gitconnected.com/typescript-keeping-type-guards-safe-and-up-to-date-2457d52bd722&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/pt/play#example/type-guards"&gt;https://www.typescriptlang.org/pt/play#example/type-guards&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>programming</category>
      <category>functional</category>
    </item>
    <item>
      <title>A Golang bot to count down the best day of your life - the holidays</title>
      <dc:creator>Luis Gustavo Macedo</dc:creator>
      <pubDate>Thu, 06 Jul 2023 18:14:16 +0000</pubDate>
      <link>https://forem.com/luisgustavom1/a-golang-bot-to-count-down-the-best-day-of-your-life-the-holidays-3b5e</link>
      <guid>https://forem.com/luisgustavom1/a-golang-bot-to-count-down-the-best-day-of-your-life-the-holidays-3b5e</guid>
      <description>&lt;p&gt;Returning with my desire to share knowledge and experience, today i will show a very cool project that i built in the last year.&lt;/p&gt;

&lt;p&gt;At the time, I was in the middle of my degree. Although I liked the university and thought that academia is very important for the education of a great software developer (but not mandatory), the holidays are a time that every university student looks anxiously.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea 💡
&lt;/h2&gt;

&lt;p&gt;Then, at the time as I already my studies in Go, and I have a idea, why not make a bot for twitter?🤔 To learn more about golang and make a cool project. &lt;/p&gt;

&lt;p&gt;A bot that makes a tweet every day telling how many days are left until college holiday, for me and people at my university accompany.&lt;/p&gt;

&lt;p&gt;Repository of project -&amp;gt; &lt;a href="https://github.com/Luisgustavom1/go-twitter-bot"&gt;https://github.com/Luisgustavom1/go-twitter-bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today that's what I want to show, I'll show the simple code of bot and how I built the infra in AWS to automate this process, obviously using the free tier🤑.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before start I have divided it into 4 main steps 📑:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a main function that must receive a date and return how many days are left until this date.&lt;/li&gt;
&lt;li&gt;Connect with twitter to make a tweet.&lt;/li&gt;
&lt;li&gt;Configure the function in AWS Lambda.&lt;/li&gt;
&lt;li&gt;Give a way of execute lambda function every day.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. The function
&lt;/h2&gt;

&lt;p&gt;The code of this feature is very simple. &lt;/p&gt;

&lt;p&gt;I have a function to format date and another to subtract the date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"math"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DaysRemaining&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VACATION_DATE&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"2023/06/29 23:00:00 -03"&lt;/span&gt;

    &lt;span class="n"&gt;vacationDateFormatted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getVacationDateFormatted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VACATION_DATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;daysToVacation&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getDaysRemaining&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vacationDateFormatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tweet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;daysToVacation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getVacationDateFormatted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;shortFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2006/01/02 15:04:05 -07"&lt;/span&gt;
    &lt;span class="c"&gt;// Format date to this format and timezone 👆👆 &lt;/span&gt;
    &lt;span class="n"&gt;dateParsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shortFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dateParsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dateParsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getDaysRemaining&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;DaysRemaining&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Subtract today from vacation date &lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;DaysRemaining&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;24&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;The main logic is basically that, in another post we can explore more about golang and its powers, but today i just want to give an overview of the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Connect with twitter
&lt;/h2&gt;

&lt;p&gt;At the time I used this &lt;a href="https://github.com/dghubble/go-twitter/"&gt;client library&lt;/a&gt; to abstract the twitter API, but unfortunately it is deprecated😭&lt;/p&gt;

&lt;p&gt;So today maybe it is not the best option. You can venture into &lt;a href="https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api"&gt;twitter api&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;In this step I had to generate api keys and access tokens. Every time I get to this part to integrate with third party, I get lost where get this secrets, so here are the ones from twitter &lt;a href="https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret"&gt;api key&lt;/a&gt; and &lt;a href="https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens"&gt;access token&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"math"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/dghubble/go-twitter/twitter"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/dghubble/oauth1"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;//...&lt;/span&gt;
    &lt;span class="c"&gt;// Initial config to oauth 1.0a&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;oauth1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_KEY_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;oauth1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ACCESS_TOKEN_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create a http client with oauth 1.0a method&lt;/span&gt;
    &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oauth1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NoContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Create the client to access twitter api methods(endpoints)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;twitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;//...&lt;/span&gt;

    &lt;span class="n"&gt;daysToVacation&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getDaysRemaining&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vacationDateFormatted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;messageToTweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateMessageToTweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daysToVacation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Method to publish a tweet&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Statuses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messageToTweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Create the Lambda Function
&lt;/h2&gt;

&lt;p&gt;At the time I only knew the concept about lambda functions so it would be one more tech that I would learn with this simple project.&lt;/p&gt;

&lt;p&gt;Let's &lt;a href="https://us-east-1.console.aws.amazon.com/lambda/home?region=us-east-1#/create/function"&gt;create lambda function&lt;/a&gt;. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose &lt;code&gt;Author from scratch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put the name of your bot.&lt;/li&gt;
&lt;li&gt;Select the language and architecture.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PWNxgf2K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwla4aiyaj2gml4bd479.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PWNxgf2K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iwla4aiyaj2gml4bd479.png" alt="AWS dashboard to create a lambda function" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, to work with Lambda using go, we have to change the code a little bit and use this &lt;a href="https://github.com/aws/aws-lambda-go/"&gt;official aws tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So we import the package, rename &lt;code&gt;main&lt;/code&gt; function to &lt;code&gt;Handler&lt;/code&gt; and create a new &lt;code&gt;main&lt;/code&gt; that will execute the &lt;code&gt;.Start()&lt;/code&gt; method, of aws tool.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Handler&lt;/code&gt; function is method that manipulate the events. The &lt;code&gt;main&lt;/code&gt; function is required, is the entry point where aws lambda will run our code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="c"&gt;// Import the package&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-lambda-go/lambda"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DaysRemaining&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// The `main` should start the Handler function&lt;/span&gt;
    &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Out function that contains the logic&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;VACATION_DATE&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"2023/06/29 23:00:00 -03"&lt;/span&gt;

    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;oauth1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_KEY"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_KEY_SECRET"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you want developing something more complexity, with multiply events and features, you can access the event name and work with context in Handler function, &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html#:~:text=func-,HandleRequest,-(ctx%20context.Context%2C%20name%20MyEvent)%20(string%2C%20error)%3A%20This"&gt;see more&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After finishing the code, don't forget of upload the code to AWS lambda, either by uploading the .zip file or by configuring an s3 bucket, and add the twitter keys in the environment variables (&lt;code&gt;Configuration&lt;/code&gt; &amp;gt; &lt;code&gt;Environment variables&lt;/code&gt;). &lt;/p&gt;

&lt;h2&gt;
  
  
  4. Running every day
&lt;/h2&gt;

&lt;p&gt;Someone once told me that&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Developers are the laziest, because they want to automate everything"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sice obviously I won't execute manually the lambda every day, we can use the AWS CloudWatch Events to trigger the function at the specific time.&lt;/p&gt;

&lt;p&gt;Then let's add a trigger&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RYOrtodA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sb38r0gb7agtgx33bxhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RYOrtodA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sb38r0gb7agtgx33bxhm.png" alt="AWS lambda dashboard to add a trigger" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;code&gt;EventBridge (CloudWatch Events)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;Create a new rule&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;Schedule Expression&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put the cron expressions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my bot I use this cron &lt;code&gt;cron(00 09 ? * * *)&lt;/code&gt;, It will run every day at 09:00 UTC, that is, 06:00 in GTM-3.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nu0PuZFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dv19ztt229gqx8mt4j8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nu0PuZFn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dv19ztt229gqx8mt4j8.png" alt="Process to create the trigger" width="800" height="773"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If when creating your lambda function, you kept these configs checked (the default configs): &lt;code&gt;Permissions&lt;/code&gt; &amp;gt; &lt;code&gt;Change default execution role&lt;/code&gt; &amp;gt; &lt;code&gt;Create a new role with basic Lambda permissions&lt;/code&gt;. You won't have to worry with the IAM role for lambda access the cloud watch, the AWS already create the role for you, &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html"&gt;lambda permissions&lt;/a&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it, see the bot perfil in &lt;a href="https://twitter.com/BotFeriasUfu"&gt;twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hope you are enjoying.&lt;/p&gt;

&lt;p&gt;Follow me on social networks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/luisgustavom1/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Luisgustavom1"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>aws</category>
      <category>twitter</category>
      <category>programming</category>
    </item>
    <item>
      <title>Typescript - Type System</title>
      <dc:creator>Luis Gustavo Macedo</dc:creator>
      <pubDate>Mon, 03 Jul 2023 12:56:10 +0000</pubDate>
      <link>https://forem.com/luisgustavom1/typescript-type-system-15dd</link>
      <guid>https://forem.com/luisgustavom1/typescript-type-system-15dd</guid>
      <description>&lt;p&gt;Hi guys, &lt;/p&gt;

&lt;p&gt;I have always wanted to produce content about programming and technology from some of the subjects I know, so that more people can learn. &lt;/p&gt;

&lt;p&gt;So I am getting courage and starting to produce content. &lt;/p&gt;

&lt;p&gt;Besides sharing knowledge I also intend to learn a lot from these articles. As I am not a genius and do not know everything, so please correct me, give suggestions, theories and let's make this space a environment for discussion and exchange of experiences and knowledge. &lt;/p&gt;

&lt;p&gt;I rolled a lot in the introduction, so let to that is important.&lt;/p&gt;

&lt;h2&gt;
  
  
  You know typescript?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do you know how to extract the maximum of typescript?
&lt;/h3&gt;

&lt;p&gt;In this article we will create a &lt;strong&gt;type system&lt;/strong&gt; for the a &lt;strong&gt;query builder&lt;/strong&gt; to study and explore the maximum of the typescript. So will focus on the type and not in the implementation. &lt;a href="https://www.typescriptlang.org/play?#code/MYewdgzgLgBAtgTwCICMCSkoEMzAKYwC8MA3gL4xYQxJbYBCVeAKntANwBQnomlRMAIoBXPACcE9YQEsANgBNxAOnl0sKJgApEqDNBz4AlJxgwlAMzEg4mgETCI428dNLHsvMCiaA2renytgA0MLbAYnh0ePIA+nTBoXhwWHK2ALouZgDuABbieHZJKbICAFxFqSEkMBWypYnJcgACtUqgcLYwZJlKKDIKmsac0mBQ4uZY+DAAqo5ipCYwAfVgwnAo4lymYFhwePXQYiMA5ls1jXUwhydnAA5UEFkgYvIHUEdgp4vCt6pjsXR6rQxmdwpF-nEoEColwyNwRmMxBMpgAFKzyYReBamZYwVbrTaLHZ7N4fL6mRQQcLSW5QaTgUk3Ra3I74FZrDZiUERKIAqE0GGcOHDUbjSYEADyL3E2KWrzxHMJpgc4hiuPxnLu6MxUDV8o1SpgAEdhDg6VAEOyCVzFmDeZDoSChdwLbcCMCsIxHKxoAISN85vVZoaWSAMV56miwzqzs9FGJ6lL47DuIpgLIsBE8bs2PcpiJxJJ+vHZeZhLg6eAYH91EwADxIegAPk08hQQPohnqBYkUjk8YAsngoDkwxAG82U5xXQQe0X++IhyOx3XFo2gotmOoPDUAB5jMDyagAazwCBA5ho9AEp-Pl-XiwAwiBZGtIHuD0eYLeL1efFuUA8NIbzPX9G3-bc8DSDdTGfV84EgABlPAPC8aIPzwQ9qAAQTEMQsAQOs4LfCAmwEXD8MI4iENIjcyOIf1TEsax6jrZgMKwmAAI8FtsEA-YuMMIgyLnPsFEXYdRyPCcQmYJsYKuFDPH5OtEI4r8KIIoiXxI+iYE0qidJopsWwgepEKEwgRNEXtiwk5dpPXLjIJCajIBCRD5MWXJ8lYxZTAAdXU6gBywU8AryCJEPeE5tPg98ADIrhiz4vNMUwADVgpgABRfd8K8Nz6AQCL8jrAKyMWFt-JgLJ6gChTTAAN3qaofAAaSWMAYAytIOwg-i0h8LKkrciBgLhUxLOswsxMHSSVyc7i8Fcoz3JgMbkNQ-40pgPp+3qQZhJgKM4GkRw6xRaRgGPCcBqA1b4ogLblOiHwDTENITOdacEDdGBQvCyK8GislV1gtbsuuT4QkWCU3XwqBnihlLjgEZ84HuI4IHAeHxDoZ4IFhzKsFfAg8H3TCv2htHiBpzg9IAAwAEhINyKFZvHEeeChSlZjLSdEMhGa4X7-oxrHztxhGCbEahiFsQhOgAH1COsmxV0ImyVmBVdsOsldFmdcvyyYoCKkrgdU949NB7LAbwUqotRusRnMGVHybRYAH4NsWFY8CazYgA"&gt;Final code&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What is the query builder?
&lt;/h4&gt;

&lt;p&gt;As this is not the proposal, I asked for the GPT&lt;br&gt;
"A query builder is a software tool or library that allows developers to construct database queries in a more intuitive and efficient way. Instead of writing raw SQL statements, which can be complex and error-prone, a query builder provides a higher-level abstraction that enables users to build queries using a more human-readable and structured syntax."&lt;/p&gt;

&lt;p&gt;We will build 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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&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="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id = :id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://orkhan.gitbook.io/typeorm/docs/select-query-builder#:~:text=QueryBuilder%20is%20one%20of%20the%20most%20powerful%20features%20of%20TypeORM%20%2D%20it%20allows%20you%20to%20build%20SQL%20queries%20using%20elegant%20and%20convenient%20syntax%2C%20execute%20them%20and%20get%20automatically%20transformed%20entities."&gt;TypeOrm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knexjs.org/guide/query-builder.html#knex-query-builder"&gt;KnexJs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kysely.dev/"&gt;kysely&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will learn and have a little notion about &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generics&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;keyof&lt;/code&gt; operator&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;infer&lt;/code&gt; operator and &lt;code&gt;conditional&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;manipulate strings&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mapped&lt;/code&gt; and &lt;code&gt;Indexed Access&lt;/code&gt; types&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  #1 Mapping the database and table of query
&lt;/h3&gt;

&lt;p&gt;In this step we will use some of &lt;code&gt;generics&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First we have to type the function which will server as builder, how this function use the design pattern &lt;a href="https://refactoring.guru/design-patterns/builder"&gt;&lt;strong&gt;builder&lt;/strong&gt;&lt;/a&gt;, do not forget to return the own function to  make this composition &lt;code&gt;.from(...).select(...).where(...)&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using this database shape for tests&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Use  this DB for tests&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DataBaseTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&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;blockquote&gt;
&lt;p&gt;Init of query builder&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DataBaseTest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DataBaseTest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&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;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RGAX1y5QkWIhQAFKIqIUEYHE2JlKtAxMICxsauKakkQQ6AhcUmDAiiBiGloEUlxI-tR0UNa29tDwSMgA8ipYeAR+5LlBBBSYUIa1AXmSme6eYK2q7Q3IAI4UcODAYACeOYH5THEQFkYmyOaQBbgA9JtomARgABbA6KsAQsgwysiQHOi4U1Ioa3CnshAAKjHeALw+jc1kDCDLoeLxkVzdLySZTRKBkCqwjbRBDCOBQFAhVjoGSlACKFGgk1OFBEsL+FwoIC8SRAyD0YDgNDeAAoiDQzPoXm9PhwAJRkfGE4mk6AAWQgh3c6A2DxQgqgRJJwlh4slRBOv2qFzcVDIzIZNGEYQA1hBJooYKtOa9MDywLzkN8AHzIeWKkVQVUHKUAGiYNCVqmZDudyAhVGOEAAPAA3RTEJ24Gy4BDJDjIKiTUw0ACSIA4Y1KmqsyFkVoZNo+X0YuDdwuV0AAdPTGSzM9m8wWqRBeUxtsgAERNaAD5AAH0HIJ6o4nA5hI6YjZgOuZc8qUAHvYIjYDpODQA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  keyof
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;keyof&lt;/code&gt; takes all the keys of the object and returns the union them.&lt;br&gt;
Then, in this case all &lt;strong&gt;keys&lt;/strong&gt; of DataBaseTest, that 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="c1"&gt;// "user" | "product" | "order"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Tables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DataBaseTest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Dynamic?
&lt;/h4&gt;

&lt;p&gt;But that way our queryBuilder is not dynamic. If we want to use it in another &lt;strong&gt;database&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;So add a &lt;code&gt;generic&lt;/code&gt; to get the database that was selected via params of &lt;code&gt;database()&lt;/code&gt; methods.&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;declare&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&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;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&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;type&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&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="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&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;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RGAX1y5QkWIhQAFKIqIUEYHE2JlKtAxMICxsauKakkQQ6AhcUmDAiiBiGloEUlxI-tR0UNa29tDwSMgA8ipYeAR+5LlBBBSYUIa1AXmSme6eYK2q7Q3IAI4UcODAYACeOYH5THEQFkYmyOaQBXbgxU7IznCTrOA+Nf31cxn7h72sYAAW7mQARAtEE4-IAD7Ij9E0b5ILJbGMBmCwbIqOUoAYTgUGOhFOs06lwg4EMN3uqmeUAgrzA7y+Pwgf3xAJxQJWa0suBsuAA9HS0JgCHdgOhVgAhZAwZTISAcdC4KZSFBrOAc2QQAAqMW8AF54U1oGQMIMuh4vGRXN0vJJlNEoGQKgaNsKUABBECKO7QMU0SXIBXVZBKw1MtUo8Baz1gDbRBDCWEoEKsdAyUoARQo0EmHIoIgN8JgFBAXiSIGQejAcHtmAAPKYOQA+AAURBoZg5AEoyFGY3GE9AALIQO7udAF4umyYi5B1qCx+PCA0tttEDuFouOpNuKhkEvZmjCMIAawgk0UME5VcdU-7g8bUFHmInxYANEwaEPVCWd3Kp9qqGyIHmAG6KYhFmm2BDJDjIKhJlMGgAEkQA4MZSidKxkFkVZ9HFSUZQ4RhcH3Bth2gAA6LMc0lEtAOAsCINTCAqyYBlvldAlvnVHoaMefVoEeJgsJgWcS0YyooEeciCCwq8E1vH8-28MZrVuW1QPA7NSOnbAYLgy0JNtBDc2pNDowHDCDRwtT8PEm0oCImTILIijGUeajPlon0WP49jFCoTiZAOVF8T45ABOvW8gA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;generic&lt;/code&gt; will capture the type that was passed in &lt;code&gt;database()&lt;/code&gt; method and pass to &lt;code&gt;QueryBuilderMethods&lt;/code&gt; for him use as he sees fit.&lt;/p&gt;

&lt;p&gt;With this change the build became dynamic, it can receive any database&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;myDbInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DataBaseTest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// "user" | "product" | "order"&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;order&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="nx"&gt;build&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;anotherDbInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AnotherDatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anotherDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// "user" | "payment"&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;payment&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="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  #2 Mapping the all columns of table selected
&lt;/h3&gt;

&lt;p&gt;In this step we'll add the &lt;code&gt;.select()&lt;/code&gt; method, that can receive all columns of table, in other words, receive all keys from the table.  &lt;/p&gt;

&lt;p&gt;How the &lt;code&gt;.select()&lt;/code&gt; depends on what was passed on &lt;code&gt;.from()&lt;/code&gt;, we have to add one more generic, the &lt;code&gt;Table&lt;/code&gt; in question.&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&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="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;s&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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Table&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&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;The &lt;code&gt;extends&lt;/code&gt; in generic, works like typing for him. The &lt;code&gt;Table&lt;/code&gt; can receive the keys of &lt;code&gt;DB&lt;/code&gt; and added a default value that is &lt;code&gt;keyof DB&lt;/code&gt;&lt;br&gt;
But if you test, &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0GxbhxSH2TAAlQyJKBTQXWQnSmIPKQ9Hjaa1VBLQ8dXrxQ6CJgXWjkJL0GQAIJQKBwLbCsOB5Dpl3irPQnMMk2q80arVF60lsvIGhm1SSnvRjFUZ4QYUAN0UxHF53cCFyHGQVC2phoAEkQBx1m1YdgXMhZI59CCwZCOIxcLnB7iAHT8wVgyUHo9T3PLlMyYT840UKhJQAIhxaBoPlJhrmQAB1cEADFMIAQiwsCKwgEJJQAbWg6CAF1EIIT8p1ZWdcCAA"&gt;ts playground&lt;/a&gt;, it won't work yet, why?&lt;/p&gt;

&lt;p&gt;That's because we made it too generic. Then we have add more specificity in some points.&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&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="c1"&gt;// Here, needs specify the table, not any `key` of `DB`&lt;/span&gt;
  &lt;span class="na"&gt;from&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;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;s&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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Don't forget to always pass the generics to &lt;/span&gt;
  &lt;span class="c1"&gt;// `QueryBuilderMethods`, in all methods, it will serve for &lt;/span&gt;
  &lt;span class="c1"&gt;// the next method that is used in the builder&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&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;We already have that &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0GxbhxSH2TAAlQyMLwch3Z7vU6aC6pQLMwlwfKQ9Hjaa1VBLQ8dXq7chweKHQRro5cgByUKfKDcLXfRTIODCeRwLYvGRyb4PFCdkDQYAIF5gHtMRsAA2LqvNGq1FetS+roF7wmEyFYVvQu9C8hEh5GADcUO3kIubo8UFOPUfN4Ex-pCC9hhAiIQvLPsgNBmriTCYC6aLIJK6BkAAglAUCDsKYaBm8ADaGYugAuuKBbQkWDImmuFoftaVY1s6EB1kwoGsmQkoEdGGJUM8EDCteijEOK5zuAguQcEeWymDQACSIAcOsbSwtgLi9i8wKgpgkIcIwuCrmB0AAHT8oKYKSlQIniZJApchA8pMNpcaKFQkoAEQ4tA9mWQ2NztA8DzIAAmrYDxWZBEAhJKGH2cQ9nVvZhw1PoEXIPZqzrNk2z2ThrnINp9HmkxuBAA"&gt;ts playground&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  #3 &lt;code&gt;.where()&lt;/code&gt; method
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;em&gt;WHERE user.id = 1&lt;/em&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea of this method is receive a string with condition, and a object with the values that will be used in the condition.&lt;/p&gt;

&lt;p&gt;The string should follow this pattern &lt;code&gt;"column operator :value" &lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's create a utility to make the where string and add new &lt;code&gt;.where()&lt;/code&gt; method&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;]&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="c1"&gt;// ...,&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="na"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MakeWhereString&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&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="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MakeWhereString&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;Column&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;Operator&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ComparisonOperators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Operator&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; :&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ComparisonOperators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Beyond utility, i moved &lt;code&gt;keyof DB[Table]&lt;/code&gt; to &lt;code&gt;Columns&lt;/code&gt; generic for more readability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0H7UwAMKKYTUEAvd2e71hwNvADaTpoLoAuiHff602LM86IDmHeL8z0PgEqGRheDkEmIF6XlmXVKBdmEuD5SHK8bTWqoJaHjq9XbkODxQ6CJgXWjkJL0GQAIJQKBwLbCmNxqgJ8V96EDhkm1XmjVasfWidT0szpjyB7QBKSpgEeRkdVwP0AdWfNgAMpJNwO6xvGLwAGSJAUD4EEeJ4qmaFpXuO9p3t2cHIDQyFkJKCHIBiVDPBAwoAG6KMQ4rnO4hrIN+f4ARAwEFMK0bgfuTYei23rqDwk5MO0gKbmAXzNq2ME8PmMZUDIXDoLkQnQPoyjoAJBAAGpwHGrrcRJfGaPmBncLglawgABgAJNgu7xi4yDWUpInKPZJDWVpOkuOZjD-FsgLIDJcnPIpwkqVALywgARNCkXIAAPsgkXCuKsUJZF4oxfFiXCjFPkILkHDIFQWymDQACSCYClyKCwtg9myI4+ggmCkIcD5g7nriAB0-KCmCkrFaVFUcOsSDykwXUwLWkqRcM0CReNBBdfOEAhJK6aRcQkWTpFhw1Po22JQIQjCJFOaLcgXVPi+M3EPmJBbRdXU4ay+G4EAA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;where&lt;/code&gt; can only accept one string that has &lt;code&gt;"column_of_table_selected ComparisonOperators :value"&lt;/code&gt;&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="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;order&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="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="c1"&gt;// ERROR: Only receive columns of order table&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;field = :id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;order&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="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="c1"&gt;// ERROR: Only receive one of operators&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id === :id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;order&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="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="c1"&gt;// ERROR: Must have the ":"&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id = id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the errors &lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0H7UwAMKKYTUEAvd2e71hwNvADaTpoLoAuiHff602LM86IDmHeL8z0PgEqGRheDkEmIF6XlmXVKBdmEuD5SHK8bTWqoJaHjq9XbkODxQ6CJgXWjkJL0GQAIJQKBwLbCmNxqgJ8V96EDhkm1XmjVasfWidT0szpjyB7QBKSpgEeRkdVwP0AdWfNgAMpJNwO6xvGLwAGSJAUD4EEeJ4qmaFpXuO9p3t2cHIDQyFkJKCHIBiVDPBAwoAG6KMQ4rnO4hrIN+f4ARAwEFMK0bgfuTYei23rqDwk5MO0gKbmAXzNq2ME8PmMZUDIXDoLkQnQPoyjoAJBAAGpwHGrrcRJfGaPmBncLglawgABgAJNgu7xi4yDWUpInKPZJDWVpOkuOZjD-FsgLIDJcnPIpwkqVALywgARNCkXIAAPsgkXCuKsUJZF4oxfFiXCjFPkILkHDIFQWymDQACSCYClyKCwtg9myI4+ggmCkIcD5g7nriAB0-KCmCkrFaVFUcOsSDykwXUwLWkqRcM0CReNBBdfOEAhJK6aRcQkWTpFhw1Po22JQIQjCJFOaLcgXVPi+M3EPmJBbRdXU4ay+HuB1yHQD1TVCpgA0leVlWjRAT1TYoVAzTi81PSta0bVtO17ccB07as6zZNsZ0XdcHQgMIWzIDYSDAGRKD5XuCbIGmUNQN8pYTddNgzTAwAQOa92PRNL3mm9uAfcO31dv1g2AyN1Wg9NkU0wtE2w2A62bUQh27dUyNgMraMbJj51MDj7R4wTRMQCTKC5KbQaKKFonhQzTG3UQIbQrCD1K093NELz-MXlAgt9X9IvDVVY0TWDENS10UAy0tcsKwjiVIxA9jq6jaxa1sWO6zc6rDKEDxwKT3zPolJCRbbN2K-mnNLe7+FAA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;a href="https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html"&gt;template literal types&lt;/a&gt; in typescript is very useful, this is a simple approach to use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  #4 Extract the column of where string
&lt;/h3&gt;

&lt;p&gt;Now we will use &lt;code&gt;infer&lt;/code&gt; and &lt;code&gt;conditional&lt;/code&gt;to extract the which column that was specified &lt;/p&gt;

&lt;p&gt;Let's make a utility type for 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;ExtractColumnByWhere&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Str&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;Str&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;MakeWhereString&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;C&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;C&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;infer&lt;/code&gt; basically extracts from within another type structure, some type. Combining with conditional, we can return this type if typescript could infer the type correctly. &lt;a href="https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types"&gt;Read more about infer keyword&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let's put all this into our structure and make the object with the values using &lt;code&gt;mapped types&lt;/code&gt;&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;],&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="c1"&gt;//...&lt;/span&gt;
  &lt;span class="na"&gt;where&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;W&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;MakeWhereString&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;V&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ExtractColumnByWhere&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="na"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;v&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="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Columns&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0H7UwAMKKYTUEAvd2e71hwNvADaTpoLoAuiHff602LM86IDmHeL8z0PgEqGRheDkEmIF6XlmXVKBdmEuD5SHK8bTWqoJaHjq9XbkODxQ6CJgXWjkJL0GQAIJQKBwLbCmNxqgJ8V96EDhkm1XmjVasfWidT0szpjyB7QBLCpgEADqTY9Le96rgfofs+NgAMpJNwO6xvGLwAGSJAUD4EAQABq37Ji8ACiHqbiEu7xq8WxAS+wofpWTBSu+yDyGQH6zkhABuZDYMg6YANKELyyE5nKJbdjm6aoXBeH7ugeZuAQR4niqZoWle472ne3aIcgNAyWQkqScgGJUM8EDCvRijEOK5zuIayD-oBwEQGBBRvgQwm8s2rbwTwk5MO0gKbmAXxOd66g8PmMZUDIXDoLkHnQPoyjoG5KFwHGro-s5-maPmKXcLglawgABgAJNgDkuMg+URV5yhFSQ+XIfFDIuNljD-FsgLIEFIXPOFnlRVALywgARNCvXIAAPsgvXCuKg0jb14oDcNo3CgNDVmVhnCIGADkEURNjCjZWXIDZaG-i8FkQFt1ngcKoAwFgUbGQQAD8LVMJEED0TEuAILkHDIFQWymDQACSCYClyKCwtgRWyI4+ggmCkIcA1g7nriAB0-KCmCkq-f9QMcOsSDykwKMwLWkq9cM0C9YTBAo-OEAhJK6a9cQvWTr1hw1PorOjQIQjCL1ObU8gKNPi+ZO8yI+YkBL-OTsxMtkL1MsAAIyyjn1UINLhCyjqmshpQA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html"&gt;Mapped types&lt;/a&gt; is a way to create new types of objects without repeating yourself, it iterates over the &lt;code&gt;union&lt;/code&gt; of keys and creating the new object.&lt;/p&gt;

&lt;p&gt;Works 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;type&lt;/span&gt; &lt;span class="nx"&gt;NewObjectKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NewObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;NewObjectKeys&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="c1"&gt;// Result in: {&lt;/span&gt;
&lt;span class="c1"&gt;//     key: string;&lt;/span&gt;
&lt;span class="c1"&gt;//     key1: string;&lt;/span&gt;
&lt;span class="c1"&gt;//     key3: string;&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?ssl=10&amp;amp;ssc=1&amp;amp;pln=1&amp;amp;pc=1#code/C4TwDgpgBAchDuB5ARgKwgY2AaQiAzlALxQBEA1nqVAD5mUgCM1dFeAzKQFCiSwIp0WYlADeULlCgBtbFACWAO35I0mHHnwBdAFxR8wAE5KA5lwC+XAPRWx121KkM9B44pMBue46d5GLo1MvGx8oBnYAt09vSyA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  #5 Make the &lt;code&gt;build&lt;/code&gt; return
&lt;/h3&gt;

&lt;p&gt;In the end, we need of the columns selected in the &lt;code&gt;.select()&lt;/code&gt; methods, to make the return of our query builder.&lt;/p&gt;

&lt;p&gt;Let's make a simple change to capture selected columns from generics&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// New Generics, based on the table columns&lt;/span&gt;
  &lt;span class="nx"&gt;ColumnsSelected&lt;/span&gt; &lt;span class="kd"&gt;extends&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;Columns&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;Columns&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;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;from&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;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Here should be more specific, not just any columns array, but the columns array that is passed by params&lt;/span&gt;
  &lt;span class="c1"&gt;// and pass this columns again to return of .select() through generics of QueryBuilderMethods&lt;/span&gt;
  &lt;span class="na"&gt;select&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;S&lt;/span&gt; &lt;span class="kd"&gt;extends&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;Columns&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;Columns&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;where&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;W&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;MakeWhereString&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;V&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ExtractColumnByWhere&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;W&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="na"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;v&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="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;V&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Don't forget of pass the generics to  `QueryBuilderMethods`&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ColumnsSelected&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0H7UwAMKKYTUEAvd2e71hwNvADaTpoLoAuiHff602LM86IDmHQRrsgAHIQeTIADiEBA0GACHQduQQswRGQuW+DxQAuzKAQsfjfwIMbjVATAGUIC6QhBe0nm96AIJQKBwLbC6cT8X5rc7vcH2focUOo+wnofAJUMjC8HINdel5Zl1S4cusjg+UhkexqmmqUCWg8Op6p24JXkwVYABLQCg6AQRQ5pdigVDKMhgIIMAMBtp2ICKKEABWwyhOsWzIGOM4Jsg5Knp2NAUKEjyjuOF4Mduu4DvohAvDIcgrl21EyDuVCTsgVbrL2QkvI8zw0Zx9FwNwQi8mAijIDYYAUFAvJpgAdJgS5gJKAGPAEFDcA8yDcM2rbtn2QbAaq5oalqEHWkwpkQGiyDCnOr4euuLwnru+4qZex48We0XilK6BkHOAHQkBDImu5FpeZB9rIJ+ECdueCadnOsEEPIg42E+TAEAA6iFyYvOqcB+vV1UQHOSTcFFdEvAAZIkBQVQQyAAGpNWFyAAKIejuIQla8WwdUhwr1UeTBSnVyDyGQ9UVmNABuZDYMg6YANKELy405nKJYjjm6aTUNJXoHmbiVjcpi5AA5KEnxQA5oRpvJA4oA5LYlAp2nIAABm5Zo5Va6Bw0waUZSqSOeSjUEFaWxXRYT-ULmZK6jSxrJkBZgHIBiVDPBAwpHYoxDiuc7iGsgrXtZ13UFMK0YqVN77DTwnZMO0gI7lpUAi966g8PmMZUOJzy5FL0D6MoHbIEw41wHGrqhaLiuaPmZvcLgN7wwAJNgJUuMg9uazLyhOyQ9sG0bLhw4w-xbICyAq2r6Aa9L2tQC8sIAETQjHyAAD7IDHwrignycx+K8dJynwrx-7XNzZwiBgEtK2dUFnA2-z8stW1ECrTY-M8MKoAwFgUbswQAD8wdMJEEBHTEuBjgmoRUFspg0AAkuP6xtLeTuyI4+ggmCkIcP7Y8cAx+aI6BRn8oKYKSpP09zxwC8QPKTBGTAD6SjHwzQDHt8ECZi7+eZ6Yx8QMedhjocGo+gAEpwEEIYQMcczv2QEZKqSEn4QJEPmEgyCoGdjOugsgMd0EAAF0FGTHFQBOLhYFGUpuaCyQA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have the columns selected, can use the &lt;code&gt;Pick&lt;/code&gt; and &lt;code&gt;Indexed Access&lt;/code&gt; to return object with only keys we selected in &lt;code&gt;.select()&lt;/code&gt;&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;QueryBuilderMethods&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Table&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Columns&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;ColumnsSelected&lt;/span&gt; &lt;span class="kd"&gt;extends&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;Columns&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;Columns&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;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...,&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;ColumnsSelected&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="o"&gt;&amp;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;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgKoGdrIN4ChnLAAmAXMiAK4C2ARtANz7lxURnphSgDmjBEVOMAA27Tjz7IADnHToA7gHsopZBy4heTClKJxIRAPr6yAEX0RJCKBAtGTyc5EYBfXLlCRYiFAAUoikQUCGA4TMRklLQMTCAsbGrimpJEEOjWwFJgwIogYhpaBFJcSJHUdFBWNnbGYGYWru6e0PBIyADyKlh4BBHk5TEEFJhQhn1RFZLFgcFgY6oTg8gAjhRw4MBgAJ5l0ZVM1rYGtfXOuG64APSXaJgEYAAWwOiOAELIMMrIkBzouNtSFBOOCvWQQAAqaVCAF4wkMRmQMEtpkEQmR-DMQpJlKkoGROrjGrhUghhHAbMxWOgZG0AIoUaBbV4UES4uEfCggEI5EDIPRgOA0MEAHlMrwAfAAKIg0MyvACUZHpjOZrOgAFkII9AuhRRKiQCUMqoEyWcJcZrtURdUwxQAaJjgwXCFAQAAekBA1uQAGsIFtFDA3shYX6A0H7UwAMKKYTUEAvd2e71hwNvADaTpoLoAuiHff602LM86IDmHQQY3GqAmAMoQF0hCBEZBJiBel4AQSgUDgW2FVfj6HF+e7vf7g5rw4dI9hPQ+ASoZGF4NbHvb3qzLqlAuzCXB8pDI+NprVUEtDx1ertyHB4oragbEDRyGFtbXya7Pb7A9jQ9nyBjj+k4JuKUroGQtaHtCx4MiaqrmhqWqXta163qWN4gegN61veTDyA80AJMKTAEAA6h+G4vOqcB+mRhE2LWSTcL+1YJsgABkiQFHhBAEAAapRHbIAAoh6vYhCBrxbPRRHCmRI5MFKpHIPIZBkQ+BAAG5kNgyDpgA0oQvL8TmcolnuObpoJXFYXmbgENBsEqmaFrIVe9roXumF-lOPlseg9aNgYvHIDQrlkJKTnIBiVDPBAwq+MACA+nqFm5v5Q5Bc+BjposUA5mB5zuIayA0XRDEQExBQkZWvm8m2wnqDwN5MO0gK9mAXyNd6zWaPmMZUDIXDoLk7XQPoyjYcgTD8XAcauuuTXMfmfXcLgAEAAYACTYCBLjILt42dcoB0kLtc0LS4m2MP8WyAsgg3Dc8Y0dZNUAvLCABE0JfcgAA+yBfcK4p-YDX3ir9ANA8Kv23aVYmcIgYBSTJlVvpwAHVUJ3rlRAsmMcxwqgDAWBRuKTAAPyPUwkQQFpMS4AguQcMgVBbKYNAAJIJgKXIoHOB2yI4+ggmCkIcLdzO88gcD5ieCG4gAdPygpgpK7OczzHDrEg8pMErMCLpKX3DNAX36wQSuYMFkrpl9xBfTeX2HDU+hO0DAhCMIX05pbyBKwRREm17Ij5iQoc+zeemR2QX2RwAApHSvM1Qf0uP7SvhayUVAA"&gt;Ts playground&lt;/a&gt;&lt;br&gt;
What a workaround this is?&lt;br&gt;
I confess that this is not at all pretty, but I thought this approach was nice.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Indexed Access&lt;/code&gt; we can get a specific type from an indexed type. How &lt;code&gt;ColumnsSelected&lt;/code&gt; is a array, we can access all its elements by accessing your &lt;code&gt;number&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Some examples&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;arrayNumbers&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ArrayNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;arrayNumbers&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SpecificNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ArrayNumbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// 1 | 2 | 3 | 4 | 5&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SpecificNumbersIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ArrayNumbers&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="c1"&gt;// 3&lt;/span&gt;

&lt;span class="c1"&gt;// Works with object&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?ssl=14&amp;amp;ssc=41&amp;amp;pln=6&amp;amp;pc=1#code/MYewdgzgLgBAhgJwXAngOQK4FsBGBTBCGAXhgG0BGAGhgCYaBmGgFhoFYBdeI0SKAbgBQUFAAc8MAIJJUmXASKkR4kADN4M9NnyFhYiQGVxwAJaqTwOTsVTNVhWTDaCHPeJhG8p85eeEAkmAAJngAHiS2yFryhGS0roIA9IkwAOogCADWRADuJlAAFjAgOABWXlCCJmBQBKpwwBIAqhAEMADegjAwJkEAXDBOMULdYHBYeAPQCNUA5iMweFhwJgA2U1AzYPNdMKJwEBA5Gf0w03MLGKJBcLVBAPq3AwAit3hCAL5uza0IAKLLNYRFoEMgAIiWK1WYK4yTOmzmQA"&gt;Ts playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. Now we have a query builder fully typed and you probably won't get the column syntax wrong again.&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myDbInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&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="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// Only accept the user keys&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email = :email&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="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// String only accept correct user table keys, specific Operators and specific object as second parameter &lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// Returns -&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// {&lt;/span&gt;
&lt;span class="c1"&gt;//   id: number;&lt;/span&gt;
&lt;span class="c1"&gt;//   email: string;&lt;/span&gt;
&lt;span class="c1"&gt;//   password: string;&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to test the code &lt;a href="https://www.typescriptlang.org/play?#code/MYewdgzgLgBAtgTwCICMCSkoEMzAKYwC8MA3gL4xYQxJbYBCVeAKntANwBQnomlRMAIoBXPACcE9YQEsANgBNxAOnl0sKJgApEqDNBz4AlJxgwlAMzEg4mgETCI428dNLHsvMCiaA2renytgA0MLbAYnh0ePIA+nTBoXhwWHK2ALouZgDuABbieHZJKbICAFxFqSEkMBWypYnJcgACtUqgcLYwZJlKKDIKmsac0mBQ4uZY+DAAqo5ipCYwAfVgwnAo4lymYFhwePXQYiMA5ls1jXUwhydnAA5UEFkgYvIHUEdgp4vCt6pjsXR6rQxmdwpF-nEoEColwyNwRmMxBMpgAFKzyYReBamZYwVbrTaLHZ7N4fL6mRQQcLSW5QaTgUk3Ra3I74FZrDZiUERKIAqE0GGcOHDUbjSYEADyL3E2KWrzxHMJpgc4hiuPxnLu6MxUDV8o1SpgAEdhDg6VAEOyCVzFmDeZDoSChdwLbcCMCsIxHKxoAISN85vVZoaWSAMV56miwzqzs9FGJ6lL47DuIpgLIsBE8bs2PcpiJxJJ+vHZeZhLg6eAYH91EwADxIegAPk08hQQPohnqBYkUjk8YAsngoDkwxAG82U5xXQQe0X++IhyOx3XFo2gotmOoPDUAB5jMDyagAazwCBA5ho9AEp-Pl-XiwAwiBZGtIHuD0eYLeL1efFuUA8NIbzPX9G3-bc8DSDdTGfV84EgABlPAPC8aIPzwQ9qAAQTEMQsAQOs4LfCAmwEXD8MI4iENIjcyOIf1TEsax6jrZgMKwmAAI8FtsEA-YuMMIgyLnPsFEXYdRyPCcQmYJsYKuFDPH5OtEI4r8KIIoiXxI+iYE0qidJopsWwgepEKEwgRNEXtiwk5dpPXLjIJCajIBCRD5MWXJ8lYxZTAAdXU6gBywU8AryCJEPeE5tPg98ADIrhiz4vNMUwADVgpgABRfd8K8Nz6AQCL8jrAKyMWFt-JgLJ6gChTTAAN3qaofAAaSWMAYAytIOwg-i0h8LKkrciBgLhUxLOswsxMHSSVyc7i8Fcoz3JgMbkNQ-40pgPp+3qQZhJgKM4GkRw6xRaRgGPCcBqA1b4ogLblOiHwDTENITOdacEDdGBQvCyK8GislV1gtbsuuT4QkWCU3XwqBnihlLjgEZ84HuI4IHAeHxDoZ4IFhzKsFfAg8H3TCv2htHiBpzg9IAAwAEhINyKFZvHEeeChSlZjLSdEMhGa4X7-oxrHztxhGCbEahiFsQhOgAH1COsmxV0ImyVmBVdsOsldFmdcvyyYoCKkrgdU949NB7LAbwUqotRusRnMGVHybRYAH4NsWFY8CazYgA"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/Luisgustavom1/cdc154c180f3969efdabb9d383ff9e26"&gt;Gist&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I hope you understood and left here with some new knowledge.&lt;/p&gt;

&lt;p&gt;That's it guys, I want to bring more in-depth content on these subjects and other things from the world of technology.&lt;/p&gt;

&lt;p&gt;This month I will create a routine of bringing you some articles every week&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>functional</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
