Typing in JavaScript has always been an issue for developers. Because of its dynamic typing nature, it is difficult for developers coming from strongly typed languages like C# or Java to adjust to using JavaScript. TypeScript was introduced to solve this problem, but there are still some desired features lacking.
One example is the JSON.parse()
function. TypeScript infers that the result of this function is of the type any
, which introduces some issues because it gives a false impression that the provided response is safe to work with. This could lead to unwanted bugs. A more expected approach would have been to return an unknown
type instead, forcing further validation from the developer.
Enter ts-reset, a CSS reset button for TypeScript that aims to improve types for common JS APIs. In this tutorial, we’ll explore how to use and set up ts-reset for TypeScript applications.
We’ll cover the following:
ts-reset is an open source package that provides a set of rules that modify TypeScript’s built-in typings. ts-reset helps improve TypeScript typing and makes it more consistent with user expectations. It also makes the code more readable and maintainable and avoids bugs caused by type errors. You can think of this package as a TypeScript version of css-reset, which is a list of rules that reset all the default browser styles, removing potential inconsistencies between different browsers.
The TypeScript type default for several built-in functions isn’t great. The following are two examples where the default TypeScript typings result in subtle bugs:
.json
(in fetch
) and JSON.parse
both return any
.filter(Boolean)
giving out falsy valuesIntroducing ts-reset helps resolve these problems by making the typings as expected:
.json
(in fetch
) and JSON.parse
both return unknown
.filter(Boolean)
We’ll go into more detail about this in a later section. Before that, let’s look at how to set up the package in a project.
Getting started with ts-reset
is easy. The first step is to install the package:
npm i -D @total-typescript/ts-reset
Next, create a reset.d.ts
file in your project with the following code:
// Do not add any other lines of code to this file! import "@total-typescript/ts-reset";
Now you’re ready to get started! If you don’t want this global use and would prefer to only include it on a file basis, or even on a feature basis, you can opt to use the inline approach instead. To do this, simply add the specific helper you need at the top of the file:
// Makes JSON.parse return unknown import "@total-typescript/ts-reset/json-parse"; //ts-reset now applies const result = JSON.parse("{}"); // unknown
N.B., For these imports to work, you’ll need to ensure that the module is set to NodeNext or Node16 in tsconfig.json
.
Now, let’s look at some use cases for the ts-reset package by addressing the problems we listed earlier.
JSON.parse
return unknown
Before ts-reset, JSON.parse
would return any
. This can cause nasty, subtle bugs because they disable type checking on the values they describe:
// BEFORE ts-reset const result = JSON.parse({}); // any
After using ts-reset, the result of JSON.parse
changes to unknown
. We now have to either validate unknown
to ensure it’s the correct type using a tool like Zod, or cast it with as
:
// AFTER ts-reset const result = JSON.parse("{}"); // unknown
.json()
return unknown
Just like JSON.parse()
, .json()
returning any
introduces unwanted any
into your application code, which could also lead to nasty bugs:
// BEFORE ts-reset fetch("/") .then((res) => res.json()) .then((json) => { console.log(json); // any });
By forcing res.json
to return unknown
, we are aware of the need to validate the results of fetch
as we now distrust the result from the res.json()
method:
// AFTER ts-reset fetch("/") .then((res) => res.json()) .then((json) => { console.log(json); // unknown });
.filter(Boolean)
filter out falsy valuesThe default behavior of .filter
doesn’t behave as expected. Given a set of values in an array with an undefined inclusive value, applying a Boolean constructor as a filter method removes all falsy values in the array, leaving only non-falsy values. However, TypeScript still sees the types as (number | undefined)[]
, using the initial values of the array as opposed to using the newly filtered array result.
Take the code below for example:
// BEFORE ts-reset const filteredArray = [1, 2, undefined].filter(Boolean); // (number | undefined)[]
After applying ts-reset, the filter method now behaves as expected. It acts like a type predicate on the array passed in and removes any false values from the array member:
// AFTER ts-reset import "@total-typescript/ts-reset/filter-boolean"; const filteredArray = [1, 2, undefined].filter(Boolean); // number[]
Because the ts-reset package doesn’t involve any configuration from the user end, it doesn’t have any compatibility issues. Note that ts-reset is designed to be used in application code, not library code. This is because each rule you include will make changes to the global scope, meaning that users importing your library will unknowingly be using ts-reset.
ts-reset is a great utility package that helps solve the typing issue in JavaScript. In this article, we learned how we can use ts-reset to enhance TypeScript default typings to make them more predictable and bug-safe. ts-reset helps our TypeScript types behave as expected in our code. I hope you have fun using ts-reset to create great TypeScript projects!
LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.
Mutative processes data with better performance than both Immer and native reducers. Let’s compare these data handling options in React.
Radix UI is quickly rising in popularity and has become an excellent go-to solution for building modern design systems and websites.
In this article, we’ll explore CSS cascade layers — and, specifically, the revert-layer
keyword — to help you refine your styling strategy.
Nushell is a modern, performant, extensible shell built with Rust. Explore its pros, cons, and how to install and get started with it.