<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zhenghao He</title>
    <description>The latest articles on DEV Community by Zhenghao He (@he_zhenghao).</description>
    <link>https://dev.to/he_zhenghao</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%2F771775%2F9a9d7600-21fe-429b-a123-97ffb66da5f0.jpg</url>
      <title>DEV Community: Zhenghao He</title>
      <link>https://dev.to/he_zhenghao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/he_zhenghao"/>
    <language>en</language>
    <item>
      <title>Frontend vs. Backend System Design interviews</title>
      <dc:creator>Zhenghao He</dc:creator>
      <pubDate>Sun, 06 Feb 2022 19:54:27 +0000</pubDate>
      <link>https://dev.to/he_zhenghao/frontend-vs-backend-system-design-interviews-28hi</link>
      <guid>https://dev.to/he_zhenghao/frontend-vs-backend-system-design-interviews-28hi</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;As I mentioned in &lt;a href="https://www.zhenghao.io/posts/framework-for-coding-interview"&gt;my last post&lt;/a&gt;, I have been interviewing a lot for the past year - not conducting interviews, I was the candidate being interviewed. Most of the interview processes I had with big tech companies consisted of 1-2 system design rounds depending on the level of the role. Unlike traditional &lt;strong&gt;backend-focused&lt;/strong&gt; system design questions, for which you can find lots of prep resources online such as the famous &lt;a href="https://www.educative.io/courses/grokking-the-system-design-interview"&gt;grokking system design interview&lt;/a&gt; or &lt;a href="https://github.com/donnemartin/system-design-primer"&gt;system design primer&lt;/a&gt;, I didn’t know what to expect for a &lt;strong&gt;frontend-focused&lt;/strong&gt; system design interview as there are very few resources out there talking about this type of interviews.&lt;/p&gt;

&lt;p&gt;Now that I have done a fair amount of system design interviews of both types, I want to give you a summary of what to expect, especially for the frontend ones since I have been mostly working on the frontend side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Similarities
&lt;/h2&gt;

&lt;p&gt;Both frontend-focused and backend-focused system design interviews share a lot of similarities in terms of the methodology you can adopt to solve the design questions: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;starting with gathering system requirements&lt;/li&gt;
&lt;li&gt;laying out a clear plan and identifying major distinguishable components of the system&lt;/li&gt;
&lt;li&gt;proceeding to end to end api design&lt;/li&gt;
&lt;li&gt;talking about optimization&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;Other kinds of similarities include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The interviewer is relying on you to drive the presentation. You can't rely on the interviewer to have your back.&lt;/li&gt;
&lt;li&gt;While the topics can be either micro or macro, you probably won’t need to actually write code - it is rare to jam some portion of coding in the middle of a system design interview&lt;/li&gt;
&lt;li&gt;Unlike scantron school exams, both types will consist of mainly open ended questions. There probably isn’t a checklist of things for you to cover one by one. Nor are you expected to drill deep into all of those. When you realize your interviewer is biased toward a particular part of the system, which they usually do, pivot your focus to that area. Other times you focus on your strengths and lead the conversation.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Differences
&lt;/h2&gt;

&lt;p&gt;During the backend-focused system design interviews, you would spend most of the time talking about things like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;backend/server side architecture, hand waving various backend services/components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;discussing which type of database to use and how to aggregate data across different shards&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;designing SQL table schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;choosing the right the cross-region strategy if your service has a global user base&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;any other kinds of system characteristics like latency, availability, fault tolerance, etc.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For frontend-focused system design interviews, you would spend most of the time talking about stuff like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontend/client side architecture, such as the appropriate rendering pattern to choose - client side rendering, or server side rendering or static generation or something in between?&lt;/li&gt;
&lt;li&gt;What kind of data fetching mechanism to use - REST vs. GRAPHQL vs. gRPC and what should the APIs look like?&lt;/li&gt;
&lt;li&gt;Specifics about UI components

&lt;ul&gt;
&lt;li&gt;a newsfeed which has an infinite scroll behaviour with all the images lazily loaded while ensuring the client side has the aspect ratio of the images upfront to prevent layout shift.&lt;/li&gt;
&lt;li&gt;an autocomplete UI component which fetches search result data incrementally in batches while receiving images from server pushes in parallel.&lt;/li&gt;
&lt;li&gt;a gallery page which pulls images and displays them in the correct order despite the asynchrony that comes with the network requests that might cause them to arrive out of order.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;How do you leverage different layers of cache to decrease latency or support offline mode.&lt;/li&gt;
&lt;li&gt;if they want to get framework-specific, which is totally possible, they might even ask you to define a particular React components’s props or manage complex state in a React app.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;A lot times having one type of system design interviews means you can over simplify the opposite side: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In a backend system design interview, the client-side/frontend is reduced to an API layer - you don’t need to consider all the intricacies of the browser or the pesky rerenders your real-time updates would cause.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In a frontend system design interview, you can treat the backend as a black box and you don’t need to worry about how things like how to scale a database, or how your choice of using web sockets might affect the load balancers because of the need for sticky sessions support.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;But again, this is a summary of my experience and depending on who your interviewers are (are they frontend, backend and/or fullstack devs), the scope of the role and which team it is (are you going to be on a frontend team or are you expected to work across the stack and stretch into the backend?) your front end system design interview might be a bit of a hybrid where some aspects of backend system design interviews might come up.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Outside of the differences with the technical topics I needed to dig deep into during the interviews, I found there are two other interesting differences that stand out between the two types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For frontend system design interviews I was often encouraged to treat the interviewers as the &lt;strong&gt;product manager&lt;/strong&gt; and we spent some time just fleshing out the brief solution for each user story. For the backend system design interviews, we didn’t really get to talk about any user interaction (I am aware that the definition of users of your system might vary, depending on whether it is customer-facing vs. developer-facing)&lt;/li&gt;
&lt;li&gt;These two types of system design interviews also differ a lot in terms of &lt;em&gt;estimating&lt;/em&gt; certain system's needs based on the potential scale of the system. The system needs can be storage needs or throughput needs or any other types of requirements. 

&lt;ul&gt;
&lt;li&gt;It is common and expected to do these estimation during backend system design interviews since your design decision is only feasible when all of the system needs can realistically be met. &lt;/li&gt;
&lt;li&gt;But for the frontend system design interview, I rarely needed to do any &lt;strong&gt;quantitative estimation&lt;/strong&gt; - for example, when I was designing some live feed during a frontend system design interview, I didn’t need to do estimations like “&lt;em&gt;So let’s say each message was roughly 140 characters long and it is utf8 so that’s 140 bytes and an average user gets 10000 messages over a certain period of time so we ended up allocating 1.4mb memory on user devices&lt;/em&gt;”. Again, I am not saying that this would never come up during a frontend system design interview. in my experience It is just much, much more rare compared to backend ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Career Ceiling
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;I am going to talk about something that is a little tangential. I don't think this is going to be a hot take but if you just want to pass the upcoming interviews, then you are welcome to skip this part.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have done interviews for both frontend focused roles and general software engineer roles. As I went through the preparation process for the system designs interviews, it just occurred to me that there is indeed a career ceiling for a pure frontend focused software engineer role.&lt;/p&gt;

&lt;p&gt;Ok so let’s first get this out of the way - you can be extremely successful as either a frontend dev or a backend dev.  &lt;/p&gt;

&lt;p&gt;Also it is hard to discuss any topic intelligently when we cannot agree on definitions. By saying frontend devs I meant developers/engineers who solely work on the UI of a software system. And by saying career ceiling I meant the potential terminal title and the highest level such a dev/engineer can achieve in the technical individual contributor track. &lt;/p&gt;

&lt;p&gt;This is an unspoken thing and a very impolite conversation. And &lt;a href="https://twitter.com/swyx/status/1236023548227072000"&gt;there are exceptions&lt;/a&gt; to this but just statistically speaking there seems to be a career ceiling for frontend-only devs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Fighting the inertia
&lt;/h3&gt;

&lt;p&gt;Part of the ceiling comes from some traditional baggage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;modern frontend development is fairly new compared to the backend counterpart. I have seen some bias in the industry that frontend is not real engineering compared to the backend and that needs absolutely to be combated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;power structure persists for a very long time and that’s partially why most of VP Eng and CTOs out there are backend/infra devs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Economic reasoning
&lt;/h3&gt;

&lt;p&gt;I had this realization that when I was going through the backend system design interviews vs. the frontend system design interviews - the technical topics those interviews tend to cover let me think about some economic reasoning leading to the perception of a "Frontend Ceiling” as well. Your value to the company really depends on how many machines/compute/storage run through &lt;strong&gt;you&lt;/strong&gt;. As a dev/engineer, that means much money you control and frontend-only devs just don’t take as much. Of course frontend is just as hard and as important especially for consumer facing products but at the end of the day your compute is being run on someone else’s machine or device and the company just don’t value that as much as the compute that they themselves need to pay for and to scale. &lt;/p&gt;

&lt;h3&gt;
  
  
  Short-lived vs. Long-running
&lt;/h3&gt;

&lt;p&gt;On top of that, normally the frontend/web apps are short-lived on the client side - the user opens the browser tab that loads your app and after 20 minutes they might just close the tab, and all the memory allocated by your app is on their devices from that point onward. On the other hand, the backend servers/services behind probably keep running for months or even years. One implication resulting from this difference is that you can generally get away with bad code that leads to performance problems down the road in frontend apps because they are short-lived and the scale of the data they are dealing with is probably small, but you cannot ignore that in a long-running backend service.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Good luck with your interviews.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>interview</category>
      <category>career</category>
      <category>backend</category>
    </item>
    <item>
      <title>The type hierarchy tree</title>
      <dc:creator>Zhenghao He</dc:creator>
      <pubDate>Sun, 06 Feb 2022 19:52:03 +0000</pubDate>
      <link>https://dev.to/he_zhenghao/the-type-hierarchy-tree-2aba</link>
      <guid>https://dev.to/he_zhenghao/the-type-hierarchy-tree-2aba</guid>
      <description>&lt;p&gt;Try read the following TypeScript code snippet and work it out in your head to predicate whether or not there would be any type errors for each assignment:&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;// 1. any and unknown&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stringVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anyVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; 

&lt;span class="nx"&gt;anyVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stringVariable&lt;/span&gt;
&lt;span class="nx"&gt;unknownVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stringVariable&lt;/span&gt;
&lt;span class="nx"&gt;stringVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;anyVariable&lt;/span&gt;
&lt;span class="nx"&gt;stringVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;


&lt;span class="c1"&gt;// 2. `never` &lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stringVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anyVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;neverVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;

&lt;span class="nx"&gt;neverVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stringVariable&lt;/span&gt;
&lt;span class="nx"&gt;neverVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;anyVariable&lt;/span&gt;
&lt;span class="nx"&gt;anyVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;neverVariable&lt;/span&gt;
&lt;span class="nx"&gt;stringVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;neverVariable&lt;/span&gt;


&lt;span class="c1"&gt;// 3. `void` pt. 1&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;undefinedVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; 
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;voidVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;

&lt;span class="nx"&gt;voidVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;undefinedVariable&lt;/span&gt;
&lt;span class="nx"&gt;undefinedVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;voidVariable&lt;/span&gt;
&lt;span class="nx"&gt;voidVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknownVariable&lt;/span&gt;


&lt;span class="c1"&gt;// 4. `void` pt. 2&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&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="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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;p&gt;If you were able to come up with the correct answers without pasting the code into your editor and let the compiler does its job, I am genuinely going to be impressed. At least I couldn’t get them all right despite writing TypeScript for more than a year. I was really confused by this part of TypeScript which involves types like &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;unknown&lt;/code&gt;, &lt;code&gt;void&lt;/code&gt; and &lt;code&gt;never&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I realized I didn’t have the correct mental model for how those types works. Without a consistent and accurate mental model, I could only rely on my experience or intuitions or constant trial and error from playing with the TypeScript compiler. &lt;/p&gt;

&lt;p&gt;The blog post is my attempt to introspect and rebuild the mental model of TypeScript’s type system. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A warning up front: this is not a short article. You can jump directly to the section where I explore the type hierarchy tree if you are in a hurry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It is a hierarchy tree
&lt;/h2&gt;

&lt;p&gt;Turns out all types in TypeScript take their place in a hierarchy. You can visualize it as a tree-like structure. Minimally, in a tree, we can a parent node and a child node. In a type system, for such a relationship, we call the parent node a supertype and the child node a subtype.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fsupertype-subtype.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fsupertype-subtype.png" alt="alt"&gt;&lt;/a&gt;&lt;br&gt;
You are probably familiar with inheritance, one of the well-known concepts in object-oriented programming. Inheritance establishes an &lt;code&gt;is-a&lt;/code&gt; relationship between a child class and a parent class. If our parent class is &lt;code&gt;Vehicle&lt;/code&gt;, and our child class is &lt;code&gt;Car&lt;/code&gt;, the relationship is “&lt;code&gt;Car&lt;/code&gt; is &lt;code&gt;Vehicle&lt;/code&gt;”. However it doesn’t work the other way around - an instance of the child class logically is not an instance of the parent class. “&lt;code&gt;Vehicle&lt;/code&gt; is not &lt;code&gt;Car&lt;/code&gt;”.  This is the semantic meaning of inheritance, and it also applies to the type hierarchy in TypeScript. &lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle" rel="noopener noreferrer"&gt;the Liskov substitution principle&lt;/a&gt;, instances of &lt;code&gt;Vehicle&lt;/code&gt; (supertype) should be substitutable with instances of its child class (subtype) &lt;code&gt;Cars&lt;/code&gt; without altering the correctness of the program. In other words, If we expect a certain behavior from a type (&lt;code&gt;Vehicle&lt;/code&gt;), its subtypes (&lt;code&gt;Car&lt;/code&gt;) should honor it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I should mention that the Liskov substitution principle is from a 30-year-old paper written for PhD's. There are a ton of nuances to it that I cannot possibly cover in one blog post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Putting this together, in TypeScript, you can assign/substitute an instance of a type’s subtype to/with an instance of that (super)type, but not the other way around.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way I just realize the meaning of the word “substitute” changes radically depending on &lt;a href="https://www.blog.voicetube.com/archives/55539" rel="noopener noreferrer"&gt;the preposition that follows it&lt;/a&gt;.  In this blog post, when I say "substitute A with B”, it means we end up with B instead of A.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  nominal and structural typing
&lt;/h3&gt;

&lt;p&gt;There are two ways in which supertype/subtype relationships are enforced. The first one, which most mainstream statically-typed languages (such as Java) use, is called &lt;strong&gt;nominal typing&lt;/strong&gt;, where we need to &lt;em&gt;explicitly&lt;/em&gt; declare a type is the subtype of another type via syntax like &lt;code&gt;class Foo extends Bar&lt;/code&gt;. The second one, which TypeScript uses is &lt;strong&gt;structural typing&lt;/strong&gt;, which doesn’t require us to state the relationship &lt;em&gt;explicitly&lt;/em&gt; in the code. An instance of &lt;code&gt;Foo&lt;/code&gt; type is a subtype of &lt;code&gt;Bar&lt;/code&gt; as long as it has all the members that &lt;code&gt;Bar&lt;/code&gt; type has, even if &lt;code&gt;Foo&lt;/code&gt; has some additional members.&lt;/p&gt;

&lt;p&gt;Another way to think about this supertype-subtype relationship is to check which type is more strict, type &lt;code&gt;{name: string, age: number}&lt;/code&gt;  is more strict than the type &lt;code&gt;{name: string}&lt;/code&gt; since the former requires more members defined in its instances. Therefore type &lt;code&gt;{name: string, age: number}&lt;/code&gt;  is a subtype of type &lt;code&gt;{name: string}&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fsupertype-subtype2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fsupertype-subtype2.png" alt="alt"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  two ways of checking assignability/substitutability
&lt;/h2&gt;

&lt;p&gt;One last thing before we dive into the type hierarchy tree in TypeScript:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;type cast&lt;/strong&gt;: you can just assign a variable of one type to a variable of another type to see if it raises a type error. More on that later.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the &lt;code&gt;extends&lt;/code&gt; keyword -you can extend one type to another:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&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="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  the top of the tree
&lt;/h2&gt;

&lt;p&gt;Let's talk about the type hierarchy tree.&lt;/p&gt;

&lt;p&gt;In TypeScript, there are two types are that the supertypes of all other types: &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They accept any value of any type, encompassing all other types.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Ftop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Ftop.png" alt="alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This graph is by no means an exhaustive list of all the types that TypeScript has. Check out &lt;a href="https://github.com/microsoft/TypeScript/blob/main/src/compiler/types.ts#L642" rel="noopener noreferrer"&gt;the source code&lt;/a&gt; of TypeScript if you are interested to see all the types that it currently supports.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  upcast &amp;amp; downcast
&lt;/h3&gt;

&lt;p&gt;There are two types of type cast - &lt;strong&gt;upcast&lt;/strong&gt; and &lt;strong&gt;downcast&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fcast.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fcast.png" alt="alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assigning a subtype to its supertype is called &lt;strong&gt;upcast&lt;/strong&gt;. By the Liskov substitution principle, upcast is safe so the compiler lets you do it implicitly, no questions asked.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are exceptions where TypeScript disallows the implicit upcast. I will address that at the end of the post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can think of upcast similiar to walking up the tree - replacing (sub)types that are more strict with their supertypes that are more generic.&lt;/p&gt;

&lt;p&gt;For example, every &lt;code&gt;string&lt;/code&gt; type is a subtype of the &lt;code&gt;any&lt;/code&gt; type and the &lt;code&gt;unknown&lt;/code&gt; type. That means the following assignments are allowed:&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;let&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬆️upcast&lt;/span&gt;
&lt;span class="kd"&gt;let&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;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬆️upcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The opposite is called &lt;strong&gt;downcast&lt;/strong&gt;. Think of it as walking down the tree - replacing the (super)type that are more generic with their subtypes that are more strict.&lt;/p&gt;

&lt;p&gt;Unlike upcast, downcast is not safe and most strongly typed languages don’t allow this automatically. As an example, assigning variables of the &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; type to the &lt;code&gt;string&lt;/code&gt; type is downcast:&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;let&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="kd"&gt;let&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;unknown&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stringA&lt;/span&gt;&lt;span class="p"&gt;:&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;any&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬇️downcast - it is allowed because `any` is different..&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stringB&lt;/span&gt;&lt;span class="p"&gt;:&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;unknown&lt;/span&gt; &lt;span class="c1"&gt;// ❌ ⬇️downcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we assign &lt;code&gt;unknown&lt;/code&gt; to a &lt;code&gt;string&lt;/code&gt; type, the TypeScript complier gives us a type error, which is expected since it is downcast so it cannot be performed without explicitly bypassing the type checker.&lt;/p&gt;

&lt;p&gt;However TypeScript would happily allow us to assign &lt;code&gt;any&lt;/code&gt; to a &lt;code&gt;string&lt;/code&gt; type, which seems contradictory to our theory.&lt;/p&gt;

&lt;p&gt;The exception here with &lt;code&gt;any&lt;/code&gt; is because, in TypeScript the &lt;code&gt;any&lt;/code&gt; type exists to act as a backdoor to escape to the JavaScript world. It reflects JavaScript’s overarching flexibility. Typescript is a compromise. This exception exists not due to some failure in design but the nature of not being the actual runtime language as the runtime language here is still JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  the bottom of the tree
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;never&lt;/code&gt; type is the bottom for the tree, from which no further branches extend.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fbottom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fbottom.png" alt="alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Symmetrically, the &lt;code&gt;never&lt;/code&gt; type behaves like the an anti-type of the top types - &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknow&lt;/code&gt;, whereas &lt;code&gt;any&lt;/code&gt; and &lt;code&gt;unknown&lt;/code&gt; accept all values, &lt;code&gt;never&lt;/code&gt; doesn’t accept any value (including values of the &lt;code&gt;any&lt;/code&gt; type) at all since it is the subtype of all types.&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;let&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; 
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="c1"&gt;// ❌ ⬇️downcast &lt;/span&gt;
&lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="c1"&gt;// ❌ ⬇️downcast &lt;/span&gt;
&lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬆️upcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you think hard enough, you might have realized that &lt;code&gt;never&lt;/code&gt; should have an infinite amount of types and members, as it must be assignable or substitutable to its supertypes, i.e. every other type in the type system in TypeScript according to the Liskov substitution principle. For example, our program should behave correctly after we substitute &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;string&lt;/code&gt; with &lt;code&gt;never&lt;/code&gt; since &lt;code&gt;never&lt;/code&gt; is the subtype of both &lt;code&gt;string&lt;/code&gt; and &lt;code&gt;number&lt;/code&gt; types and it shouldn’t break the behavior defined by its supertypes.&lt;/p&gt;

&lt;p&gt;Technically this is impossible to achieve. Instead, TypeScript makes &lt;code&gt;never&lt;/code&gt; an empty type (a.k.a an uninhabitable type): a type for which we cannot have an actual value at runtime, nor can we do anything with the type e.g. accessing properties on its instances. The canonical usecase for &lt;code&gt;never&lt;/code&gt; is when we want to type a return value from a function that &lt;strong&gt;never returns&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A function might not return for several reasons: it might throw an exception on all code paths, it might loop forever because it has the code that we want to run continuously until the whole system is shut down, like the event loop. All these scenarios are valid.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fnThatNeverReturns&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;span class="k"&gt;throw&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;It never returns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fnThatNeverReturns&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬆️upcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assignment above might seem wrong to you at first - if &lt;code&gt;never&lt;/code&gt; is an empty type, why is that we can assign it to a &lt;code&gt;number&lt;/code&gt; type? The reason why such an assignment is fine is that the compiler knows that our function never returns so nothing will ever be assigned to the &lt;code&gt;number&lt;/code&gt; variable. Types exist to ensure that the data is correct at runtime. If the assignment never actually happens at runtime, and the compiler knows that for sure in advance, then the types don’t matter.&lt;/p&gt;

&lt;p&gt;There is another way to produce a &lt;code&gt;never&lt;/code&gt; type is to intersect two types that aren’t compatible - e.g. &lt;code&gt;{x: number} &amp;amp; {x: string}&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Baz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Bar&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Baz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Type 'string' is not assignable to type 'never'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Edit from the future: I realized that there are some nuances to the resulting type - if disjoint properties are considered as discriminant properties (roughly, those whose values are of literal types or unions of literal types), the whole type is reduced to &lt;code&gt;never&lt;/code&gt;. This is a feature introduced in TypeScript 3.9. Check out &lt;a href="https://github.com/microsoft/TypeScript/pull/36696" rel="noopener noreferrer"&gt;this PR&lt;/a&gt; for details and motivation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  types in between
&lt;/h2&gt;

&lt;p&gt;We have talked about the top types and the bottom type. The types in between are just the other regular types you use everyday - &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, composite types like &lt;code&gt;object&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;There shouldn’t be too much surprise as to how those types work once we have established the correct mental model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is allowed to assign a string literal type e.g. &lt;code&gt;let stringLiteral: 'hello' = 'hello'&lt;/code&gt; to a &lt;code&gt;string&lt;/code&gt; type (upcast) but not the other way around (downcast)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it is allowed to assign a variable holding an object of a type with extra properties to an object of a type with less properties when the existing properties’ types match (upcast) but not the other way around (downcast)&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserWithEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="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;UserWithoutEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserWithEmail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;UserWithoutEmail&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// true ✅ ⬆️upcast &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Or assign an non-empty object to an empty object:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emptyObject&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;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// ✅ ⬆️upcast &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;However there is one type I want to talk more about in this section since people often confuse it with the bottom type &lt;code&gt;never&lt;/code&gt; and that type is &lt;code&gt;void&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In many other languages, &lt;a href="https://docs.microsoft.com/en-us/cpp/cpp/void-cpp?view=msvc-170" rel="noopener noreferrer"&gt;such as C++&lt;/a&gt;, &lt;code&gt;void&lt;/code&gt; is used as the a function return type that means that function doesn't return. However, in TypeScript, for a function that doesn't return at all, the correct type of the return value is &lt;code&gt;never&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So what is the type &lt;code&gt;void&lt;/code&gt; in TypeScript? &lt;code&gt;void&lt;/code&gt; in TypeScript is a supertype of &lt;code&gt;undefined&lt;/code&gt; - TypeScript allows you to assign &lt;code&gt;undefined&lt;/code&gt; to &lt;code&gt;void&lt;/code&gt; (upcaset) but again, not the other way around (downcast) &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fvoid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.zhenghao.io%2Fart%2Fblog%2Ftype-hierarchy-tree%2Fvoid.png" alt="alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This can also be verified via the &lt;code&gt;extends&lt;/code&gt; keyword:&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;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;void&lt;/code&gt; is also an operator in javascript that evaluates the expression next to it to &lt;code&gt;undefined&lt;/code&gt;, e.g. &lt;code&gt;void 2 === undefined // true&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In TypeScript, the type &lt;code&gt;void&lt;/code&gt; is used to indicate that the implementer of a function is making no guarantees about the return type except that it won’t be useful to the callers. This opens the door for a &lt;code&gt;void&lt;/code&gt; function at runtime to return something other than &lt;code&gt;undefined&lt;/code&gt;, but whatever it returns shouldn’t be used by the caller.&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="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&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="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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;p&gt;At first blush this might seem like a violation for the Liskov substitution principle since the type &lt;code&gt;string&lt;/code&gt; is not a subtype of &lt;code&gt;void&lt;/code&gt; so it shouldn’t be able to be substitutable for &lt;code&gt;void&lt;/code&gt;. However, if we view it from the perspective of whether or not it alters the correctness of the program, then it becomes apparent that as long as the caller function has no business with the returned value from the &lt;code&gt;void&lt;/code&gt; function (which is exactly the intended outcome of the &lt;code&gt;void&lt;/code&gt; type), it is pretty harmless to substitute that with a function that returns something different.&lt;/p&gt;

&lt;p&gt;This is where TypeScript is trying to be pragmatic and complements the way JS works with functions. In JavaScript it is pretty common when we reuse functions in different situations with the return values being ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  situations where TypeScript disallows implicit upcast
&lt;/h2&gt;

&lt;p&gt;Generally there are two situations, and to be honest it should be pretty rare to find yourself in these situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When we pass literal objects directly to function
&lt;/li&gt;
&lt;/ol&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="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;{}&lt;/span&gt;

&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&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="c1"&gt;// ❌ Object literal may only specify known properties, and 'key' does not exist in type '{ name: string; }'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;When we assign literal objects directly to variables with explicit types
&lt;/li&gt;
&lt;/ol&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;UserWithEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="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;UserWithoutEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserWithoutEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&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="s1"&gt;foo@gmail.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;// ❌ Type '{ name: string; email: string; }' is not assignable to type 'UserWithoutEmail'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/type-compatibility.html#any-unknown-object-void-undefined-null-and-never-assignability" rel="noopener noreferrer"&gt;Assignability Matrix in the TypeScript official docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>An introduction to type programming in TypeScript</title>
      <dc:creator>Zhenghao He</dc:creator>
      <pubDate>Mon, 31 Jan 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/he_zhenghao/an-introduction-to-type-programming-in-typescript-37o7</link>
      <guid>https://dev.to/he_zhenghao/an-introduction-to-type-programming-in-typescript-37o7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;See discussions on &lt;a href="https://news.ycombinator.com/item?id=30173375"&gt;Hacker News&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Types are a complex language of their own
&lt;/h2&gt;

&lt;p&gt;I used to think of TypeScript as just JavaScript with type annotations sprinkled on top of it. With that mindset, I often found writing correct types tricky and daunting, to a point they got in the way of building the actual applications I wanted to build, and frequently, it led me to reach for &lt;code&gt;any&lt;/code&gt;. And with &lt;code&gt;any&lt;/code&gt;, I lose all type safety.&lt;/p&gt;

&lt;p&gt;Indeed, types can get really complicated if you let them. After writing TypeScript for a while, it occurred to me that the TypeScript language actually consists of two sub-languages - one is JavaScript, and the other is the type language. For the JavaScript language, the world is made of JavaScript values; for the type language, the world is made of types. When we write TypeScript code, we are constantly dancing between these two worlds: we create types in our type world and "summon" them in our JavaScript world using type annotations; we can go in the other direction too: use the &lt;a href="https://www.typescriptlang.org/docs/handbook/2/typeof-types.html#the-typeof-type-operator"&gt;typeof operator&lt;/a&gt; on JavaScript variables/properties to retrieve the corresponding types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ygDaE5gI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.zhenghao.io/art/blog/type-programming/twoworlds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ygDaE5gI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.zhenghao.io/art/blog/type-programming/twoworlds.png" alt="alt" width="880" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The JavaScript language is very expressive, so is the type language - in fact, the type language is so expressive that it has been proven to be Turing complete.&lt;/p&gt;

&lt;p&gt;Here I don't make any value judgment of whether being Turing complete is good or bad, nor do I know if it is even by design or by accident (in fact, often times, Turing-completeness was achieved &lt;a href="http://beza1e1.tuxen.de/articles/accidentally_turing_complete.html"&gt;by accident&lt;/a&gt;). My point is the type language itself, as innocuous as it seems, is certainly powerful, highly capable and can perform arbitrary computation at compile time.&lt;/p&gt;

&lt;p&gt;When I started to think of the type language in TypeScript as a full-fledged programming language, I realized it even has a few characteristics of a functional programming language:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;use recursion instead of iteration

&lt;ol&gt;
&lt;li&gt;in &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#tailrec-conditional"&gt;TypeScript 4.5&lt;/a&gt; we have tail call optimized recursion to some extent&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;types (data) are immutable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this post, we will learn the type language in TypeScript by comparing it with JavaScript so that you can leverage your existing JavaScript knowledge to master TypeScript quicker.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This post assumes that readers have some familiarity with JavaScript and TypeScript. And if you want to learn TypeScript from scratch properly, you should start with &lt;a href="https://www.typescriptlang.org/docs/handbook/intro.html"&gt;The TypeScript Handbook&lt;/a&gt;. I am not here to compete with the docs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Variable declaration
&lt;/h2&gt;

&lt;p&gt;In JavaScript, the world is made of JavaScript values, and we declare variables to refer to values using keywords &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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;p&gt;In the type language, the world is made of types, and we declare type variables using keywords &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;interface&lt;/code&gt;. For example:&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;Obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;The idea of "type variables" is a made-up concept - a type variable is an alias of a type, analogous to how a JavaScript variable references a value. I found drawing this analogy makes explaining concepts of the type language much easier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Types and values are very related. A type, at its core, represents the set of possible values. Sometimes the set is finite, e.g., &lt;code&gt;type Name = 'foo' | 'bar'&lt;/code&gt;, a lot of times the set is infinite, e.g., &lt;code&gt;type Age = number&lt;/code&gt;. In TypeScript we integrate types and values and make them work together to ensure that the runtime values match the compile-time types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local variable declaration
&lt;/h3&gt;

&lt;p&gt;We talked about how you can create type variables in the type language. However, the type variables have a global scope by default. To create a local type variable, we can use the &lt;code&gt;infer&lt;/code&gt; keyword in our type language.&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;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// global scope&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="c1"&gt;// *only* inside this expression, C represents A&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this particular way of creating scoped variables might seem strange to JavaScript developers, it actually finds its roots in some pure functional programming languages. For example, in Haskell, we can use the &lt;code&gt;let&lt;/code&gt; keyword with &lt;code&gt;in&lt;/code&gt; to perform scoped assignments as in &lt;code&gt;let {assignments} in {expression}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; 
&lt;span class="o"&gt;//&lt;/span&gt;                         &lt;span class="err"&gt;↑&lt;/span&gt;       &lt;span class="err"&gt;↑&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;expression&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Equality comparisons and conditional branching
&lt;/h2&gt;

&lt;p&gt;In JavaScript. we can use &lt;code&gt;===&lt;/code&gt;/&lt;code&gt;==&lt;/code&gt; with if statement or the conditional (ternary) operator &lt;code&gt;?&lt;/code&gt; to perform equality check and conditional branching.&lt;/p&gt;

&lt;p&gt;In the type language, on the other hand, we use the &lt;code&gt;extends&lt;/code&gt; keyword for "equality check", and the conditional (ternary) operator &lt;code&gt;?&lt;/code&gt; for conditional branching too as in:&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;TypeC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TypeA&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;TypeB&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;TrueExpression&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FalseExpression&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;TypeA&lt;/code&gt; is assignable or substitutable to &lt;code&gt;TypeB&lt;/code&gt;, then we enter the first branch and get the type from &lt;code&gt;TrueExpression&lt;/code&gt; and assign that to &lt;code&gt;TypeC&lt;/code&gt; ; otherwise we get the type from &lt;code&gt;FalseExpression&lt;/code&gt; as a result to &lt;code&gt;TypeC&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The concept of assignability/substitutability is one of the core concepts in TypeScript that deserves a separate post - I wrote &lt;a href="https://dev.to/posts/type-hierarchy-tree"&gt;one covering that in detail&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A concrete example in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;matched&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;username&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translate it into the type language:&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;Username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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;Matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Username&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;extends&lt;/code&gt; keyword is versatile. It can also apply constraints to generic type parameters. For example:&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;getUserName&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="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;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding the generic constraints, &lt;code&gt;&amp;lt;T extends {name: string}&amp;gt;&lt;/code&gt; we ensure the parameter our function takes always consist of a &lt;code&gt;name&lt;/code&gt; property of the type &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieve types of properties by indexing into object types
&lt;/h2&gt;

&lt;p&gt;In JavaScript we can access object properties with square brackets e.g. &lt;code&gt;obj['prop']&lt;/code&gt; or the dot operator e.g., &lt;code&gt;obj.prop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the type language, we can extract property types with square brackets as well.&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;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Name&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="s1"&gt;name&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;p&gt;This works not just with object types, we can also index the type with tuples and arrays.&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;Names&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;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Names&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Tuple&lt;/span&gt; &lt;span class="o"&gt;=&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="kr"&gt;number&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;Age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Tuple&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;Functions are the main reusable “building blocks” of any JavaScript program. They take some input (some JavaScript values) and return an output (also some JavaScript values).&lt;br&gt;
In the type language, we have generics. Generics &lt;strong&gt;parameterize&lt;/strong&gt; types like functions &lt;strong&gt;parameterize&lt;/strong&gt; value. Therefore, a generic is conceptually similar to a function in JavaScript.&lt;/p&gt;

&lt;p&gt;For example, in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ["hello", "world"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our type language, we have:&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;Fn&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&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;B&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;//   ↑    ↑           ↑                          ↑              ↑&lt;/span&gt;
&lt;span class="c1"&gt;// name parameter parameter type          default value   function body&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Fn&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// ["hello", "world"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;However, generics are by no means a perfect analogy for functions. For one, unlike functions in JavaScript, Generics are not first-class citizens in the type language. That means we cannot pass a generic to another generic like we pass a function to another function as TypeScript doesn't allow &lt;a href="https://github.com/microsoft/TypeScript/issues/1213"&gt;generics as type parameters&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Map and filter
&lt;/h3&gt;

&lt;p&gt;In our type language, types are immutable. If we want to modify a part of a type, we have to transform the existing ones into &lt;strong&gt;new types&lt;/strong&gt;. In the type language, the details of iterating over a data structure (i.e. an object type) and applying transformations evenly are abstracted away by &lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html"&gt;Mapped Types&lt;/a&gt;. We can use it to implement operations that are conceptually similar to the map and filter array methods in JavaScript.&lt;/p&gt;

&lt;p&gt;In JavaScript, let's say we want to transform an object's properties from numbers to strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&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;stringifyProp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;key&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userWithStringProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stringifyProp&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="c1"&gt;// {name:'foo', age: '28'}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the type langauge, the mapping is done using this syntax &lt;code&gt;[K in keyof T]&lt;/code&gt; where the &lt;code&gt;keyof&lt;/code&gt; operator gives us property names as a string union type.&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;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StringifyProp&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="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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&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;UserWithStringProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StringifyProp&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="c1"&gt;// { name: string; age: string; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In JavaScript, we can filter out the properties of an object based on some critiria. For example, we can filter out all non-string properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&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;filterNonStringProp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;key&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filterNonStringProp&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="c1"&gt;// {name: 'foo'}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our type language, this can be achieved with the &lt;code&gt;as&lt;/code&gt; operator and the &lt;code&gt;never&lt;/code&gt; type:&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;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FilterStringProp&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="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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;]&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;K&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;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;FilteredUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FilterStringProp&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="c1"&gt;// { name: string }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a bunch of builtin &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html"&gt;utility “functions”&lt;/a&gt; (generics) for transforming types in TypeScript so often times you don't have to re-invent the wheels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern matching
&lt;/h2&gt;

&lt;p&gt;We can also use the &lt;code&gt;infer&lt;/code&gt; keyword to perform pattern matching in the type language.&lt;/p&gt;

&lt;p&gt;For example, in a JavaScript program, we can use regex to extract a part of a string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo-bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/foo-*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&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;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 'bar'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The equivalence in our type language:&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;Str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo-bar&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;Bar&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="s2"&gt;`foo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;rest&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;rest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="c1"&gt;// 'bar'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recursion, instead of iteration
&lt;/h2&gt;

&lt;p&gt;Just like many pure functional programming languages out there, in our type language, there is no syntactical construct for for loop to iterate over a list of data. Recursion take the place of loops.&lt;/p&gt;

&lt;p&gt;Let's say in JavaScript, we want to write a function to return an array with same item repeated multiple times. Here is one possible way you can do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&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 recurisve solution would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;array&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;array&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;How do we write out the equivalence in our type language? Here are logical steps to arrive at one solution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a generic type called &lt;code&gt;FillArray&lt;/code&gt; (remember we talked about that generics in our type language are just like functions?)

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FillArray&amp;lt;Item, N extends number, Array extends Item[] = []&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inside the "function body", we need to check if the &lt;code&gt;length&lt;/code&gt; property on &lt;code&gt;Array&lt;/code&gt; is already &lt;code&gt;N&lt;/code&gt; using the &lt;code&gt;extends&lt;/code&gt; keyword.

&lt;ul&gt;
&lt;li&gt;if it has reached to &lt;code&gt;N&lt;/code&gt; (the base case), then we simply return &lt;code&gt;Array&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;if it hasn't reached to &lt;code&gt;N&lt;/code&gt;, it recurses and added one more &lt;code&gt;Item&lt;/code&gt; into &lt;code&gt;Array&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Putting these together, we have:&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;FillArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Item&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="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="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;length&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt; 
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FillArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Item&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Foos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FillArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// ["foo", "foo", "foo"]        &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Limits for recursion depth
&lt;/h3&gt;

&lt;p&gt;Before TypeScript 4.5, the max recursion depth is &lt;a href="https://www.typescriptlang.org/play?ts=4.4.4&amp;amp;ssl=3&amp;amp;ssc=10&amp;amp;pln=3&amp;amp;pc=17#code/C4TwDgpgBAShkENgDkA8BJYEC2AaKyUEAHlgHYAmAzlGQK7YBGEATvgCp1gA20J51KAjIgA2gF0oAXigSAfNKiceEUQHJeZAObAAFmsn8IlGoQD8SrrygAuWPAhI0mHPmT5RAOm-Le+F9jicgDcAFCgkFAAQopwiCioagCMavgALACsCuHg0ACCsQ5OiSnpAGwKAPSVUFTACADGANZQAPYAbqwAZtytAO5AA"&gt;45&lt;/a&gt;. In TypeScript 4.5, we have tail call optimization, and the limit increased to &lt;a href="https://www.typescriptlang.org/play?ts=4.5.4#code/C4TwDgpgBAShkENgDkA8BJYEC2AaKyUEAHlgHYAmAzlGQK7YBGEATvgCp1gA20J51KAjIgA2gF0oAXigSAfNKiceEUQHJeZAObAAFmsn8IlGoQD8SrrygAuWPAhI0mHPmT5RAOm-Le+F9jicgDcAFChoJBQAIKKcIgoqGoAjGr4AJyZchHg0ABCcQ5OSan4yQAMlQoA9NVQVMAIAMYA1lAA9gBurABm3O0A7qFAA"&gt;999&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid type gymnastics in production code
&lt;/h2&gt;

&lt;p&gt;Sometimes type programming is jokingly referred to as “type gymnastics” when it gets really complex, fancy and far more sophisticated than it needs to be in a typical application.&lt;br&gt;
For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/chinese-chess-everywhere/type-chess"&gt;simulating a Chinese chess (象棋)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.joshuakgoldberg.com/type-system-game-engines/"&gt;simulating a Tic Tac Toe game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f"&gt;implementing arithmetic&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They are more like academic exercises, not suitable for production applications because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;they are hard to comprehend, especially with esoteric TypeScript features.&lt;/li&gt;
&lt;li&gt;they are hard to debug due to incredibly long and cryptic compiler error messages.&lt;/li&gt;
&lt;li&gt;they are slow to compile.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Just like we have Leetcode for practicing your core programming skills, we have &lt;a href="https://github.com/type-challenges/type-challenges"&gt;type-challenges&lt;/a&gt; for practicing your type programming skills.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;We have covered a lot in this blog post. The point of this post is not to really teach you TypeScript, rather than to reintroduce the "hidden" type language you might have overlooked ever since you started learning TypeScript.&lt;/p&gt;

&lt;p&gt;Type programming is a niche and underdiscussed topic in the TypeScript community, and I don't think there is anything wrong with that - because ultimately adding types is just a means to an end, the end being writing more dependable web applications in JavaScript. Therefore, to me it is totally understandable that people don't often take the time to "properly" study the type language as they would for JavaScript or other programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/hediet/63f4844acf5ac330804801084f87a6d4"&gt;Proof that TypeScript's Type System is Turing Complete&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://itnext.io/typescript-and-turing-completeness-ba8ded8f3de3"&gt;TypeScript and Turing Completeness&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
    </item>
  </channel>
</rss>
