ts-jest

repository·main·Indexed 27 days ago

https://github.com/kulshekhar/ts-jest

A Jest transformer with source map support that allows developers to test TypeScript projects using Jest, supporting all TypeScript features including type-checking. Version 29.4.12. It provides tools for initializing configuration via `ts-jest config:init`, support for ESM and CommonJS transformations, and the ability to implement custom TypeScript transformer plugins using a specific boilerplate structure.

Tokens
24.7K
Snippets
84
Records
126
Agent score
91%

What's inside ts-jest

  1. Map TypeScript paths to Jest moduleNameMapper

    main

    If your tsconfig.json uses baseUrl and paths for module resolution, you must configure Jest's moduleNameMapper to match. ts-jest provides the pathsToModuleNameMapper helper to automate this transformation.

    Note: The helper requires the .js version of your config file (or an imported object) to access compilerOptions.

    To use the helper:

    1. Import pathsToModuleNameMapper from ts-jest.
    2. Import your compilerOptions from your TypeScript configuration file.
    3. Pass compilerOptions.paths to the helper.
    4. Optionally provide a prefix (e.g., <rootDir>/) to ensure paths resolve correctly relative to the project root.
    import { pathsToModuleNameMapper } from 'ts-jest'
    import { compilerOptions } from './tsconfig'
    import type { Config } from 'jest'
    
    const jestConfig: Config = {
      // [...]
      roots: ['<rootDir>'],
      modulePaths: [compilerOptions.baseUrl],
      moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
    }
    
    export default jestConfig
  2. Understand limitations of @babel/preset-typescript compared to ts-jest

    main

    When choosing between using @babel/preset-typescript and ts-jest, be aware that Babel transpiles files as isolated modules without a notion of a 'project'. This leads to several functional differences. ts-jest provides full TypeScript support, whereas @babel/preset-typescript has the following limitations:

    • No type-checking: Babel does not perform type-checking during transpilation. ts-jest performs type-checking out of the box, providing a more fluent TDD experience by throwing errors when type mismatches occur.
    • No namespace support: TypeScript namespaces cannot be used with the Babel preset.
    • No const enum support: Constant enums are not supported.
    • No declaration merging: Features like declaration merging for enum or namespace will not work.
    • No legacy import/export syntax: Syntax such as import lib = require('lib') or export = myVar is not supported.
    • No caret type-casting with JSX enabled: The <Type>value syntax for type-casting is unavailable if JSX is enabled in your Babel configuration.
  3. Understand behavior with hybrid Node module settings

    main

    When configuring your project with hybrid Node module values such as Node16, Node18, or NodeNext, be aware of the following behaviors in ts-jest:

    1. Transpilation Source: ts-jest uses the TypeScript API for transpilation. Consequently, the emitted JavaScript code is dependent on the version of TypeScript currently installed in your project.
    2. Dynamic Imports: Unlike traditional CommonJs transformations, dynamic import statements will not be transformed into Promise and require calls.

    It is recommended to consult the official TypeScript documentation regarding Node16/Node18/NodeNext module resolution to understand how your code will be emitted.

  4. Install and set up ts-jest

    main

    To use ts-jest in your project, you need to install jest, typescript, ts-jest, and @types/jest. After installation, you can initialize your configuration using the ts-jest config:init command.

    Note on TypeScript 7: If your project uses TypeScript 7, do not install typescript directly; instead, follow the supported side-by-side compiler setup guide in the official documentation.

    Note on Versioning: ts-jest does not follow Semantic Versioning (SemVer). The major version number follows the version of Jest. If you need to revert to a version before the 23.10 rewrite, install a version <23.10.0.

  5. Implement a TypeScript Transformer Boilerplate

    main

    When writing a custom TypeScript transformer plugin for ts-jest, you should follow a specific boilerplate structure. This involves exporting a version number (to invalidate Jest's cache when the transformer logic changes), a name for cache key construction, and a factory function that accepts a TsCompilerInstance.

    The factory function provides access to the TypeScript compiler module (compilerInstance.configSet.compilerModule) and returns a Transformer<SourceFile> function. Inside the transformer, you use a Visitor to traverse and potentially modify the AST nodes using ts.visitEachChild or ts.visitNode.

    import { SourceFile, TransformationContext, Transformer, Visitor } from 'typescript'
    
    import type { TsCompilerInstance } from 'ts-jest/dist/types'
    
    /**
     * Remember to increase the version whenever transformer's content is changed. This is to inform Jest to not reuse
     * the previous cache which contains old transformer's content
     */
    export const version = 1
    // Used for constructing cache key
    export const name = 'hoist-jest'
    
    export function factory(compilerInstance: TsCompilerInstance) {
      const ts = compilerInstance.configSet.compilerModule
      function createVisitor(ctx: TransformationContext, sf: SourceFile) {
        const visitor: Visitor = (node) => {
          // here we can check each node and potentially return
          // new nodes if we want to leave the node as is, and
          // continue searching through child nodes:
          return ts.visitEachChild(node, visitor, ctx)
        }
        return visitor
      }
      // we return the factory expected in CustomTransformers
      return (ctx: TransformationContext): Transformer<SourceFile> => {
        return (sf: SourceFile) => ts.visitNode(sf, createVisitor(ctx, sf))
      }
    }
  6. Understand TypeScript 7 performance and diagnostic tradeoffs

    main

    When using the TypeScript 7 side-by-side installation with ts-jest, be aware of the following behaviors:

    1. Performance: TypeScript 7's native performance improvements apply only to tsc (the native compiler). Jest transform performance remains equivalent to TypeScript 6 because ts-jest uses the compatibility API.
    2. Diagnostics: Diagnostics produced during Jest transforms are generated by the TypeScript 6 compatibility API. These may differ from the diagnostics produced by the native TypeScript 7 compiler.
    3. Best Practice: Always run npx tsc --noEmit separately in local development and CI to ensure your project passes the authoritative TypeScript 7 type-check.
  7. Migrate Jest configuration from versions <=23.10

    main

    If you are upgrading from ts-jest version 23.10 or older, you can use the config:migrate CLI tool to automatically help migrate your Jest configuration to the current format.

    Depending on how your configuration is stored, run the corresponding command below.