Unit testing negative conditions with TypeScript

TypeScript provides a certain comfort that nowhere will your functions or components be invoked with the wrong input, your code is always checked statically as you write. However, most applications have some kind of server-side API that drives its state; at this point, TypeScript is not in play because the code that executes in your browser only contains plain JavaScript. When it comes to handling external data, always follow the axiom:

Trust but verify

In a recently completed a project, we noticed that most of our unit tests were not testing for negative conditions that involve undefined/null/empty values. The reason was obvious, in the tests, TypeScript will not allow undefined or an inappropriate function argument, it just won’t compile. For a dynamically typed language running on the browser with some/all of its state managed externally, this is a big risk, functions and components cannot just rely on its internal happy paths.

The solution here is typecasting, it is quite simple. Let us consider a real example, a function that returns a named parameter from a url.

export const getParameter = (name: string, url: string) => {
const params = RegExp(`[?|&]${name}=([^&;]+?)(&|#|;|$)`).exec(url || "");
return params?.[1] || "";
};

You cannot test for null/undefined input values directly like so:

// TypeScript will not allow these.
getParameter(undefined, url);
getParameter(undefined as string, url);

You can solve this using the unknown type, this is always a two step process. First you create an unknown type that can take any value. Then, typecast it while calling the function.

const url = "http://localhost/?param1=hello&param2=world";
const nullValue: unknown = undefined;
it("getParameter returns url params", () => {
expect(getParameter("param1", url)).toEqual("hello");
expect(getParameter("param2", url)).toEqual("world");
expect(getParameter("param1", "")).toEqual("");
expect(getParameter("param1", nullValue as string)).toEqual("");
expect(getParameter(nullValue as string, url)).toEqual("");
expect(getParameter(nullValue as string, nullValue as string)).toEqual("");
});

Now your function has been tested against possible null values. Hurray.

--

--

--

Frontend Architect, San Jose, CA

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Delve into Symbol in ES6 (1)

about React functional and class components accessing props and statement management

JS 403 — 3 weeks into it

React Native - PureComponentDebug

Build Beautiful, Gradient-Enabled Circular Progress Bars in React

Learning to Code: Day 53 — Basic JavaScript Part 18

Vuex for n00bs: Learn by Doing

Verbs + preposition

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rajesh Naroth

Rajesh Naroth

Frontend Architect, San Jose, CA

More from Medium

Forcing string patterns in Typescript

How to Implement an Event Bus in JavaScript

My channel for javascript developers