14: Exploring TypeScript: Runtime
What's the deal with runtime?
8/20/20246 min read


This is part of a semi-monthly series that will put TypeScript under a microscope to become more adept overall. š¬
Understanding the nitty gritty bits and pieces of a language can only benefit us as software builders!
This post will cover runtime.
š¤ What is runtime?
𦾠Reconstruct and confirm runtime types
š Resources for further reading
Let's go!
š¤ What is runtime?
To start, letās better grasp what type of āruntimeā Iām referring to and what it actually means in that context.
Here, runtime refers to the process of a computer interpreting and performing a programās instructions. Think of each line of code in your program or file as a line of instructions to be carried out!
In the first post of this series, I wrote about the TypeScript Compiler.
What does the compiler have to do with runtime?
We learned that JavaScript code is generated from our TypeScript code through the compilation steps, which is what our runtime will use! JavaScript runtime is often executed in Node but could also be accomplished using Deno, Bun, or a web browser.
Itās interesting to note that TypeScript is statically typed. The types are checked at compile time, not runtime, like JavaScript or other dynamically typed languages. This process checks your code to help find syntax issues or correct misusage in advance.
Why is this helpful?
This allows your IDE to offer some powerful tooling and reduces errors upfront!
Issues can be caught before a user experiences something your team missed.
Youāll achieve better readability and maintainability for your future self and teammates. When written well, TypeScript reads like good documentation.
There should also be less cognitive load, scrolling, and searching for files; your IDE will show you relevant information when you mouse over variables!
What does runtime have to do with TypeScript, then?
Simply put, TypeScript types donāt exist at runtime.
Come again?
Yes, thatās right. TypeScript types are āerasable,ā removed from the compiled code. Interfaces and type annotations also fall under this umbrella of removed code. Although we havenāt covered declaration files, the types and interfaces described in these files will also disappear.
If you recall, we compile TypeScript code into JavaScript. TypeScript is a superset of JavaScript and adds more functionality on top of JavaScript.
As a result, TypeScript-specific features and functionality disappear and canāt affect your JavaScript code. Therefore, interfaces, types, and type annotations cannot affect runtime behavior.
Thatās not at all to say that TypeScript is useless! On the contrary, it empowers your JavaScript code output and developer experience if you take advantage of them, even if aspects disappear when your program hits runtime.
In my opinion, the biggest benefit of using TypeScript types is having a pre-defined āshapeā of the types you work with.
This requires thoughtful intention! Iāve worked on projects that arenāt strict with typing and it caused me some headaches. When done well, defined shapes have clarified exactly what Iām working with while building and developing.
As a simple example to play around with type āshape,ā here we define the āshapeā of an object we want to use to describe my three pets:
Before we run this code, weāll encounter issues. In VSCode, for example, a little red squiggly identifies issues with the code snippet.
We tried to use a string to describe Rayla as ā6 monthsā instead of the expected number input for her age (0, 0.5, or 1 depending on your own interpretation). Whoops! What were we thinking?
Afterward, we created an imaginary cat. Because itās not real, we arenāt sure how old it is! Bummer. Alas, Pet as an interface is looking for an age field.
Wait, this example uses an interface, and that goes away after compile time, right?
Correct; Iām so glad you brought that back to the forefront. Letās look into how you can still ensure type safety at runtime!
𦾠Reconstruct and confirm runtime types
Although TypeScript-specific features donāt exist at runtime, there are ways to ensure that runtime is safe. Donāt fret!
Hereās a great summary pulled from Effective TypeScript that is a quick way to describe some of what weāre about to cover:
If given the time to contemplate, one could probably come up with all sorts of ideas and examples. But here, weāll cover 3 I use pretty frequently, plus examples.
Validate inputs from external sources
Check types or properties to handle in your code
Use a discriminated (or ātaggedā) union
Hint: You can use the following commands to follow along with examples in #2 and #3 using TypeScript in Node!
Validate inputs from external sources
You can usually find me building APIs with TypeScript.
This means we receive data from the outside world for most endpoints, which we have no control over, sent to us. Malicious actors may send questionable data to attempt to take advantage of our API!
I recommend validation because we honestly have no idea what a user (whether malicious or misinformed) may try to send us. You could build your own, but Iāve had success using Zod. It has excellent documentation and significant support. Iāve heard Yup is also great, though I havenāt used it personally!
Using validation, we can check that the input is exactly what we need. It can even stop incorrect types in their tracks! At least in my experience with Zod, we can add all sorts of check layers to refine user input before our server fully interacts with it.
Here are a couple of examples:
Another great thing Iāve used with Zod is my own extra layer of refinement to validate the incoming data. Here are two slightly more involved examples:
ā¦And there are all sorts of maneuvers like this you can use to check your data from the outside world to ensure itās about as safe as you can manage - both for type safety and input security!
Check types or properties to handle in your code
When working with multiple potential types, itās a good idea to confirm the input's āshapeā or data type. This is great both in your TypeScript code and for runtime!
This could be a simple check when you expect, for instance, one type or another. Maybe we know a phone number could be provided as a string or a number, and letās assume we know the input has the right character count or number length already, but we want the same E164 format output for a North American phone number in either case:
Do you want more straight to your inbox?
Subscribe to receive occassional blog posts!
Your contact information will never be sold.
In this way, although TypeScript types and true type checking wonāt exist in the generated JavaScript, we can confirm which types we are working with and how we want to utilize them in a way that will translate into runtime. The generated JavaScipt code looks identical in this case!
We can use a similar concept with objects. Letās say weāre now talking about storing art pieces in galleries!
Again, the JavaScript code generated appears almost identical! The interface is the main element missing from the compiled code this time, but we can still determine a rough type using property checking in the moveArtworkToGallery function.
The property check only involves values that are available at runtime but still allows the type checker to refine the object's shape to the Art type. Thatās great TypeScript code practice and translatable JavaScript all at once!
Use a discriminated (or ātaggedā) union
This concept is similar to the object case above, and Iāve found it useful to specifically use the field name type, especially for building APIs. As a user Iāve seen it often in third-party APIs, so I feel itās a common enough practice to lean on.
We are essentially doing property checking again, but in my experience, this is often with a set list of known types. Perhaps this list is described in the API documentation.
Letās return back to the example of my three pets!
When using a discriminated union (or ātaggedā union as itās described in Effective TypeScript), we are essentially implementing some kind of type storage in our object using a ātagā that we can access and use at runtime.
How can we access this? Itās because there is also a value stored in the type field.
I hope that these examples were helpful! Considering how your runtime will read and follow your instructions through your TyeScript code after compilation may help you build better!
š Resources for further reading
Contentful: āTypeScript vs. JavaScript: Explaining the differencesā
TotalTypeScript: āNo, TypeScript Types Donāt Exist At Runtimeā
There are a few interesting exceptions to the rules here covered more in-depth: enums, namespaces, and parameter properties.
Log Rocket: āMethods for TypeScript runtime type checkingā
OāReilly Books:
Learning TypeScript by Josh Goldberg
Iām reading this as of this writing. Iāve seen him speak, and his humor and conciseness come across well in print!
TypeScript Cookbook by Stefan Baumgartner
It was unread by me as of this writing, but itās on my list.
Thanks so much for reading! āØ
Did I miss anything, or would you like to add anything?
Let me know!
I appreciate constructive feedback so we can all learn together. š
Connect
You can find Mindi Weik on these platforms:
mindi@wip-podcast.com
Ā© 2025. All rights reserved.
![[WIP] Podcast logo](https://assets.zyrosite.com/cdn-cgi/image/format=auto,w=375,fit=crop,q=95/Yan01MjyJEH16nVN/black-background-AMqDQ54p9xtwjbqg.png)