npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jmlweb/tsconfig-base

v1.0.5

Published

Base TypeScript configuration with strict type checking and modern defaults

Downloads

864

Readme

@jmlweb/tsconfig-base

npm version License: MIT Node.js TypeScript

Base TypeScript configuration with strict type checking and modern defaults. Designed to be extended by projects without imposing file inclusion/exclusion patterns.

✨ Features

  • 🔒 Strict Mode: All strict flags enabled for maximum type safety
  • 🚀 Modern Defaults: ES2022 target with NodeNext module resolution
  • 🛡️ Extra Safety: Additional strict checks beyond the strict flag
  • 🎯 Flexible: No include/exclude defined - you control what gets compiled
  • 🗺️ Source Maps: Enabled by default for debugging

📦 Installation

pnpm add -D @jmlweb/tsconfig-base typescript

💡 Upgrading from a previous version? See the Migration Guide for breaking changes and upgrade instructions.

🚀 Quick Start

Create a tsconfig.json file in your project root:

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

💡 Examples

Node.js Project

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Library with Multiple Entry Points

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src",
    "composite": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

Monorepo Package

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src",
    "composite": true,
    "declarationDir": "./dist"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

React Project

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src",
    "jsx": "react-jsx"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Overriding Options

You can override any option in your project's tsconfig.json:

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "target": "ES2020",
    "noUncheckedIndexedAccess": false
  },
  "include": ["src/**/*"]
}

📋 Configuration Details

Compiler Options Included

| Option | Value | Description | | ------------------------------------ | ---------- | ---------------------------------------------- | | strict | true | Enables all strict type checking options | | target | ES2022 | Modern JavaScript features | | module | NodeNext | Node.js ESM module system | | moduleResolution | NodeNext | Node.js module resolution | | esModuleInterop | true | CommonJS/ESM interoperability | | skipLibCheck | true | Skip type checking of declaration files | | forceConsistentCasingInFileNames | true | Enforce consistent file name casing | | declaration | true | Generate .d.ts files | | declarationMap | true | Generate sourcemaps for .d.ts files | | sourceMap | true | Generate sourcemaps for debugging | | noUncheckedIndexedAccess | true | Add undefined to index signatures | | noImplicitOverride | true | Require override keyword | | noPropertyAccessFromIndexSignature | true | Require bracket notation for index signatures | | exactOptionalPropertyTypes | true | Differentiate between undefined and optional | | noFallthroughCasesInSwitch | true | Report fallthrough cases in switch | | isolatedModules | true | Ensure compatibility with transpilers | | verbatimModuleSyntax | true | Enforce explicit type imports/exports | | resolveJsonModule | true | Allow importing JSON files |

What You Need to Configure

Since this base config intentionally omits file patterns, you must configure:

  • include: Which files to compile (e.g., ["src/**/*"])
  • exclude: Which files to ignore (e.g., ["node_modules", "dist"])
  • outDir: Output directory for compiled files
  • rootDir: Root directory of source files (optional but recommended)

🎯 Why No File Patterns?

This base config intentionally omits include and exclude patterns because:

  • ✅ Different projects have different file structures
  • ✅ You maintain full control over what gets compiled
  • ✅ Prevents conflicts with project-specific patterns
  • ✅ More flexible for various project types

🤔 Why Use This?

Philosophy: TypeScript should catch bugs at compile time through strict type checking. If it compiles without errors, it should work correctly.

This package provides an opinionated TypeScript configuration that enables all strict flags and additional safety checks. It's designed to prevent common JavaScript pitfalls through TypeScript's type system while remaining flexible enough for any project type.

Design Decisions

All Strict Flags Enabled (strict: true + extras): Enables strict null checks, no implicit any, strict function types, etc.

  • Why: TypeScript's strict mode catches entire classes of bugs (null/undefined errors, implicit any holes, binding issues). Additional flags like noUncheckedIndexedAccess catch even more edge cases
  • Trade-off: More initial type errors when adopting, requires explicit null handling. But this prevents runtime crashes
  • When to override: For gradual migration from JavaScript (but aim to enable all flags eventually)

Modern Target (ES2022): Compiles to ES2022 with modern JavaScript features

  • Why: Modern Node.js and browsers support ES2022. Using modern features provides better performance and cleaner output. Let your runtime handle the code
  • Trade-off: Requires Node.js 18+ or modern browsers. If targeting older environments, override with ES2020 or lower
  • When to override: When supporting legacy environments (but consider transpiling separately)

NodeNext Module Resolution: Uses Node.js ESM resolution algorithm

  • Why: Matches how Node.js resolves modules in real projects. Prevents module resolution mismatches between TypeScript and runtime
  • Trade-off: Requires proper package.json exports and file extensions in imports. But this matches modern JavaScript standards
  • When to override: For legacy projects using CommonJS exclusively (but you should migrate to ESM)

No File Inclusion: Doesn't specify include or exclude patterns

  • Why: Different projects have different structures (src/, lib/, packages/). Config shouldn't impose opinions about project layout
  • Trade-off: Must define your own include/exclude in project tsconfig.json (but you'd do this anyway for custom needs)
  • When to override: Never - add include/exclude in your project's tsconfig.json

Source Maps Enabled: Generates source maps for debugging

  • Why: Source maps enable debugging TypeScript source in Node.js and browsers. Essential for production debugging
  • Trade-off: Slightly larger build output, but negligible compared to debugging benefits
  • When to override: If you're absolutely certain you don't need debugging (rare)

🎯 When to Use

Use this configuration when you want:

  • ✅ Strict TypeScript type checking for maximum type safety
  • ✅ Modern JavaScript features (ES2022)
  • ✅ Node.js ESM module system
  • ✅ Flexible file inclusion/exclusion patterns
  • ✅ Foundation for extending with framework-specific configs

For React projects, use @jmlweb/tsconfig-react instead.

For internal tooling projects, use @jmlweb/tsconfig-internal instead.

🔧 Extending the Configuration

Using ES Modules (ESM)

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}

Using CommonJS

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "node"
  }
}

Less Strict Configuration

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "noUncheckedIndexedAccess": false,
    "exactOptionalPropertyTypes": false
  }
}

📝 Usage with Scripts

TypeScript compilation is typically handled by your build tool or IDE. For manual compilation:

{
  "scripts": {
    "build": "tsc",
    "typecheck": "tsc --noEmit"
  }
}

📋 Requirements

  • Node.js >= 18.0.0
  • TypeScript >= 5.0.0

📦 Peer Dependencies

This package requires the following peer dependency:

  • typescript (>= 5.0.0)

📚 Examples

See real-world usage examples:

🔗 Related Packages

Internal Packages

External Tools

  • TypeScript - Strongly typed programming language that builds on JavaScript
  • ts-node - TypeScript execution engine for Node.js
  • tsx - Fast TypeScript/ESM execution (alternative to ts-node)
  • ESLint - Linter for TypeScript (use with @jmlweb/eslint-config-base)

⚠️ Common Issues

Note: This section documents known issues and their solutions. If you encounter a problem not listed here, please open an issue.

Missing File Extensions Error

Symptoms:

  • Error: "Relative import paths need explicit file extensions in ECMAScript imports"
  • Import statements like import { foo } from './bar' fail

Cause:

  • This config uses moduleResolution: "NodeNext" which follows Node.js ESM rules
  • Node.js requires explicit .js extensions in import statements (even for .ts files)

Solution:

Add .js extensions to your imports (TypeScript will resolve to .ts files):

// Before
import { foo } from './bar';

// After
import { foo } from './bar.js';

Or switch to a bundler-based module resolution:

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}

Module and ModuleResolution Mismatch

Symptoms:

  • Error: "Option 'module' must be set to 'NodeNext' when 'moduleResolution' is 'NodeNext'"
  • Type errors related to module resolution

Cause:

  • Both module and moduleResolution must be set to compatible values
  • This config uses NodeNext for both

Solution:

If you need to override the module system, update both options together:

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}

CommonJS vs ESM Mismatch

Symptoms:

  • Code runs but module resolution is incorrect
  • require statements in output when you expected import

Cause:

  • Your package.json has "type": "module" but your build uses CommonJS
  • Or vice versa

Solution:

Match your package.json to your build output:

// package.json
{
  "type": "module" // For ESM output (this config's default)
}

Or override to CommonJS:

// tsconfig.json
{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "node"
  }
}

Index Signature Type Errors

Symptoms:

  • Error: "Object is possibly 'undefined'" when accessing object properties
  • Example: obj[key] shows type T | undefined

Cause:

  • This config enables noUncheckedIndexedAccess for extra safety
  • TypeScript correctly adds undefined to index access types

Solution:

Use optional chaining or explicit checks:

// Before
const value = obj[key].toString();

// After - option 1: optional chaining
const value = obj[key]?.toString();

// After - option 2: explicit check
if (obj[key] !== undefined) {
  const value = obj[key].toString();
}

// After - option 3: type assertion (use sparingly)
const value = obj[key]!.toString();

Or disable this strict check:

{
  "extends": "@jmlweb/tsconfig-base",
  "compilerOptions": {
    "noUncheckedIndexedAccess": false
  }
}

🔄 Migration Guide

Upgrading to a New Version

Note: If no breaking changes were introduced in a version, it's safe to upgrade without additional steps.

No breaking changes have been introduced yet. This package follows semantic versioning. When breaking changes are introduced, detailed migration instructions will be provided here.

For version history, see the Changelog.

Need Help? If you encounter issues during migration, please open an issue.

📜 Changelog

See CHANGELOG.md for version history and release notes.

📄 License

MIT