Unit testing negative conditions with TypeScript

Use the “unknown” type

Rajesh Naroth
2 min readNov 2, 2020

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.

--

--