Bits Kingdom logo with a hexagon lattice, uppercase text in white, and a minimalistic design.

Strictly Typed: Configuring and Testing TypeScript Projects

From Zero to Production-Ready Code - Chapter 7

Home / Development / Strictly Typed: Configuring and Testing TypeScript Projects

Over time, I’ve realized that TypeScript truly shines when paired with the right tools. A well-configured project not only improves developer experience but also ensures code quality and long-term maintainability. In this chapter, we’ll cover how to set up a reliable TypeScript configuration, integrate it with ESLint and Prettier, and write fully typed tests with Jest and React Testing Library. These practices form the backbone of professional TypeScript projects.

3D TypeScript logo for a series of posts.

1. Understanding and Configuring tsconfig.json in TypeScript

Your tsconfig.json file controls how TypeScript compiles and checks your code. Getting it right is essential for productivity and consistency.

Basic Example:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "jsx": "react-jsx",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "outDir": "dist",
    "baseUrl": "./",
    "paths": {
      "@components/*": ["src/components/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

Key Options Explained:

  • paths & baseUrl: Enable clean and manageable import paths.
  • strict: Enables strict type checking for maximum safety.
  • jsx: Set to react-jsx or react depending on React version.
  • esModuleInterop: Improves compatibility between CommonJS and ES modules.

2. ESLint Setup for TypeScript Projects

Linting enforces coding standards and catches subtle bugs.

Install Dependencies:

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

Create .eslintrc.js

module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module"
  },
  plugins: ["@typescript-eslint"],
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  rules: {
    "@typescript-eslint/no-explicit-any": "warn",
    "@typescript-eslint/explicit-function-return-type": "off"
  }
};

3. Prettier Integration with TypeScript

Prettier ensures your codebase stays consistently formatted.

Install Prettier and Integration:

npm install --save-dev prettier eslint-config-prettier

Update ESLint Config:

extends: [
  "plugin:@typescript-eslint/recommended",
  "prettier"
],

Add .prettierrc

{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all"
}

Format on Save in VS Code:

// .vscode/settings.json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

4. Writing Typed Tests with Jest and TypeScript

Testing with types helps you spot issues before they reach production.

Install Jest with TypeScript:

npm install --save-dev jest ts-jest @types/jest
npx ts-jest config:init

Basic Unit Test Example

// src/utils/math.ts
export function add(a: number, b: number): number {
  return a + b;
}
// src/utils/math.test.ts
import { add } from './math';

test('adds numbers correctly', () => {
  expect(add(2, 3)).toBe(5);
});

5. Testing React Components with React Testing Library

For UI tests, React Testing Library integrates beautifully with TypeScript.

Install Dependencies:

npm install --save-dev @testing-library/react @testing-library/jest-dom @types/testing-library__jest-dom

Example Component Test

// Button.tsx
type ButtonProps = {
  label: string;
  onClick: () => void;
};

export const Button = ({ label, onClick }: ButtonProps) => (
  <button onClick={onClick}>{label}</button>
);
// Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

test('renders the button and handles click', () => {
  const onClick = jest.fn();
  render(<Button label="Click Me" onClick={onClick} />);
  
  const btn = screen.getByText(/click me/i);
  fireEvent.click(btn);

  expect(onClick).toHaveBeenCalled();
});

6. Running Tests and Linting in CI/CD Pipelines

Automating tests and linting ensures your code remains consistent across environments and teams.

Add NPM Scripts:

{
  "scripts": {
    "build": "tsc",
    "lint": "eslint . --ext .ts,.tsx",
    "format": "prettier --write .",
    "test": "jest"
  }
}

CI Example (GitHub Actions)

name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm run lint
      - run: npm run test
      - run: npm run build

Quick Recap

  • tsconfig.json: Central to controlling your TypeScript build and checks.
  • ESLint + Prettier: Keep your codebase clean, consistent, and error-free.
  • Typed Tests: Use Jest for logic and React Testing Library for UI, both fully typed.
  • CI/CD Integration: Automate tests and linting for reliable workflows.

Coming up next: Taking TypeScript to Production: Performance and Best Practices—learn how to bundle, optimize, and confidently ship TypeScript applications at scale.

About the author

<a href="https://bitskingdom.com/blog/author/heberlyn/" target="_self">Heberlyn Mendoza</a>
Heberlyn Mendoza
I have been building my experience as a Full Stack Developer for around 5 years. I'm passionate about challenges, finding issues and blockers to explore my creativity and ingenuity, and then getting the satisfaction of getting things done. I always like to do different things, move on, and learn something different every day.

Explore more topics:

Back to Basics: Are E-commerce Websites a Better Bet Than Apps?

The classic strategy for small businesses