CI/CD for TypeScript Projects: GitHub Actions Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Do You Need Advanced CI/CD for TypeScript?

A basic CI/CD pipeline that simply runs npm test and npm build becomes inefficient as soon as your TypeScript project starts to grow. Build times increase, tests take hours, and manual version management leads to errors. An advanced level of GitHub Actions configuration allows you to solve these problems: speed up the pipeline with caching, run tests in parallel for different Node.js versions and OS, and automate deployment to production.

In this article, we will cover three key techniques for TypeScript projects: intelligent caching of node_modules, matrix builds for compatibility checks, and automated deployment using actions/upload-pages-artifact. All examples are written in TypeScript and ready to be integrated into your repository.



1. Intelligent Caching of Dependencies and Compilation

The first problem with large TypeScript projects is the long installation of dependencies and compilation. GitHub Actions provides a caching mechanism, but it needs to be configured correctly. Instead of caching the entire node_modules folder (which can lead to outdated versions), it is better to cache package-lock.json and the compiler's .cache folder.

Example of advanced caching for TypeScript:

name: TypeScript CI (Advanced)on: [push, pull_request]

jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Cache TypeScript cache uses: actions/cache@v4 with: path: | **/node_modules **/.tsbuildinfo key: ${{ runner.os }}-ts-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-ts- - run: npm ci - run: npm run build --if-present - run: npm test

The key optimization here is using hashFiles('**/package-lock.json') to generate a unique cache key. If package-lock.json hasn't changed, the cache is restored in seconds. The --if-present flag allows skipping the build script if it is not defined.



2. Matrix Builds: Testing on Different Node.js Versions and OS

TypeScript compiles to JavaScript, but code behavior can differ in different runtime environments. The GitHub Actions matrix strategy allows you to run the same pipeline on multiple combinations of OS and Node.js versions. This is critical for libraries and server applications.

Example of matrix configuration for a TypeScript project:

jobs:  test:    runs-on: ${{ matrix.os }}    strategy:      matrix:        os: [ubuntu-latest, windows-latest, macos-latest]        node-version: [18, 20, 22]        exclude:          - os: windows-latest            node-version: 22      fail-fast: false

steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm ci - run: npx tsc --noEmit - run: npm test - name: Upload coverage uses: actions/upload-artifact@v4 with: name: coverage-${{ matrix.os }}-${{ matrix.node-version }} path: coverage/

Key points:

  • fail-fast: false — does not stop other jobs if one fails. Allows you to see all problems at once.
  • exclude — allows you to exclude known non-working combinations (e.g., Node 22 on Windows if there is a known issue).

Blogs

Book Recommendations