Testing TypeScript with Jest

typescript and react

Note: this is the fourth entry in a short series about creating React/Redux applications with TypeScript. Part one introduced a simple counter application, which we then dressed up with a simple React UI and API interactions. Read on!

Followers of this blog won’t need to be convinced of the value of a well-maintained test suite. And lucky for us, Jest makes it nearly painless to test React applications–even with TypeScript in the mix. Let’s look at the layers involved in developing clean, test-secured code.


In vanilla JavaScript, linting validates syntax as a first line of defense against runtime errors. In TypeScript, static type-checking serves a similar purpose, though with a more sophisticated understanding of the raw syntax’s context. But linters have a secondary purpose: ensuring maintainability. Even with a type-system handling the heavy lifting of static analysis, we still benefit from linting for legible, consistent style.

Fortunately for us, tslint is a first-rate TypeScript linter with configuration and use familiar from JavaScript tools like jshint or eslint. After installing tslint, and initializing a default configuration, we’re ready to lint a new or existing project:

$ npm install -g tslint
$ tslint --init
$ tslint -c tslint.json 'src/**/*.{ts,tsx}'

Setting up Jest

Jest is a low-configuration testing harness popular in React applications, and for good reason: in vanilla JavaScript, it mostly Just Works™. That’s a big deal for developers used to wrestling with PhantomJS (you know who you are–and if you don’t, just use Jest).

Using Jest with TypeScript takes a little more effort. Facebook’s Jest/TypeScript example outlines the strategy: set up a preprocessor for any TypeScript files; run Jest as before. ts-jest is a great option for preprocessing, providing compilation, source-mapping, and an all-around pleasant preprocessing experience. It’s available via npm:

$ npm install --save-dev ts-jest

Now, to start testing we need only add a new top-level entry for "jest" into the project’s package.json:

"jest": {
  "moduleFileExtensions": [
  "transform": {
    "\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
  "testRegex": "/__tests__/.*\\.(ts|tsx|js)$"

While package.json is open, let’s add scripts for linting and testing to see all of our hard work in action:

"scripts": {
  "lint": "tslint -c tslint.json 'src/**/*.{ts,tsx}'",
  "pretest": "npm run lint",
  "test": "jest"

Add some tests

At this point, our tests read the same as they would in JavaScript. Let’s write a simple spec that will verify future changes of our <Counter /> component using a snapshot made possible, as all good things are, by Jest.

// src/components/__tests__/counter_spec.tsx
import * as React from 'react'
import * as TestUtils from 'react-addons-test-utils'

import { createStore } from 'redux'

import { Counter } from '../counter'
import { reducers } from '../../reducers'

describe('<Counter />', () => {
  it('renders', () => {
    const store = createStore(reducers)
      <Counter label='a counter!' store={store} />

By rendering the component with a shallow renderer, we’re able to compare to a snapshot exactly as we would in JavaScript. All that’s left is to watch it turn green.

$ npm test


And there you have it: the basic tools, configurations, and scripts to make testing a central part of a TypeScript application. We don’t have to stop here! Though it’s an exercise for another day, the same techniques we use to validate code and write unit tests can just as easily apply in end-to-end testing.

The completed counter project is available for reference on github, tests and all. Have an comment, suggestion, or improvement? The issue queue is open for business. And I’m looking forward to your suggestions, experiences, and feedback over on twitter!

Happy testing!

Note: this is the fourth installment of a short series about bolstering Redux applications with TypeScript. Next, we’ll revisit our API interactions, using the redux-thunk middleware to tie them up. Read on!

Let's stay in touch! Share this post or subscribe for (very) occasional updates.

Hey, I'm RJ! Writer, speaker, sustainable development advocate, and inconsistent micropoet, broadcasting live from Portland.

Posted 12/10/2016