TL;DR — Here is a boilerplate project that reflects what is explained

Lets gradually build up our configuration, understanding and resolving issues as they surface.

Important: You can clone this Github project as you walk through the guide.

Step 1: Setting up a basic service.

Within the project folder run git checkout step-1 . We have a simple web server with the following directory structure.

.

+-- src

| +-- lib

| | +-- database

| | | +-- index.ts

| +-- repositories

| | +-- person

| | | +-- index.ts

| +-- services

| | +-- person

| | | +-- index.ts

| +-- index.ts

+-- test

| +-- lib

| | +-- database

| | | +-- index.spec.ts

| +-- repositories

| | +-- person

| | | +-- index.spec.ts

| +-- services

| | +-- person

| | | +-- index.spec.ts

Importing the repository module requires the service to traverse up their directory and into the the repositories directory leading the following:

import * from ../../repositories/person . This becomes quite verbose as your project grows in size.

Step 2: Configuring path resolution on tsconfig.js

Run git checkout step-2 . Setting the baseUrl and paths specifies to the Typescript transpiler how to resolve modules.

baseUrl: Specifies where to find modules for all imports, all non-relative imports are considered to be relative this.

paths: Configures how to resolve specific names, relative to the baseUrl.

Step 3: Configuring the NodeJS runtime to handle module resolution

Within the project folder run git checkout step-3 . Everything runs well on using ts-node and when you compile it using tsc .

However trying to run the transpiled code fails throwing an error like.

Error: Cannot find module '@/services/person'

at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)

at Function.Module._load (internal/modules/cjs/loader.js:506:25)

...

The NodeJS runtime does not know how to resolve our aliases. This is because the tsconfig is only applicable to the Typescript compiler and is not picked up Nodejs runtime. More on this is detailed in this issue on the Typescript repository.

It would be great if the compiler also handled rewriting the generated files.

Unfortunately it doesn’t and we need to specify to the NodeJS runtime how to resolve modules.

We can use a npm module called module-alias to do just that. It has other great features that allow you to define aliases on the fly.

Add the following to the beginning of the src/index.ts to register the module.

require('module-alias/register')

We append a _moduleAliases to our package.json .

Running the newly transpiled code from the dist folder, runs now without any issues.

Step 4: Configuring the Jest runtime to resolve modules.

Within the project folder run git checkout step-4 . If you tried running the tests any time until now, it probably failed to run and threw an error:

Cannot find module '@/repositories/person' from 'index.spec.ts' > 1 | import * as personRepository from '@/repositories/person'

| ^

2 | import { findById, getAllPersons } from '@/services/person'

3 |

4 | describe('findById', () => {

By now I am pretty sure, you definitely get the idea. Jest needs a way to figure out how to resolve the modules. We use the moduleNameMapper property to specify module resolution using regular expressions and how to resolve matching paths.