get-tsconfig

Find and parse `tsconfig.json` files. ## Features - Tiny! `9 kB` Minified + Gzipped - Tested against TypeScript for correctness - Resolves [`extends`](https://www.typescriptlang.org/tsconfig/#extends) - Fully typed `tsconfig.json` - Validates and throws parsing errors

Already a sponsor? Join the discussion in the Development repo!

## Install ```bash npm install get-tsconfig ``` ## Why? TypeScript tooling (bundlers, linters, loaders, test runners) needs to read `tsconfig.json` to understand compiler options, path aliases, and file inclusion rules. But TypeScript's own config parser is buried inside the compiler and requires TypeScript as a dependency. `get-tsconfig` provides the same functionality as a lightweight, standalone library — tested against TypeScript for correctness. ## Quick start ```ts import { getTsconfig, isFileIncluded, resolvePathAlias } from 'get-tsconfig' // Find and parse the nearest tsconfig.json const tsconfig = getTsconfig() // To resolve path aliases (compilerOptions.paths): if (tsconfig) { const resolved = resolvePathAlias(tsconfig, '@/utils/helper') // → ['/project/src/utils/helper'] } // To check if a file belongs to this tsconfig: if (tsconfig && isFileIncluded(tsconfig, '/project/src/index.ts')) { // Use tsconfig.config.compilerOptions for transformation } ``` ## Finding & reading tsconfig These functions find, read, and parse tsconfig files from the filesystem. All return a `TsconfigResult`: ```ts type TsconfigResult = { path: string config: Config sources: string[] } ``` - **path**: absolute path to the tsconfig file - **config**: the fully resolved config (extends merged, options normalized) - **sources**: paths of all tsconfig files that contributed to the resolved config via [`extends`](https://www.typescriptlang.org/tsconfig/#extends). When there are no `extends`, this is just `[path]`. Since `extends` can be an array, the order does not imply a linear chain. ### getTsconfig(searchPath?, options?) Searches for a tsconfig file and parses it. If you already know the path, use [`readTsconfig`](#readtsconfigtsconfigpath-options) instead. Returns `undefined` if not found. #### searchPath Type: `string` Default: `process.cwd()` Path to a file or directory. The directory tree is searched up for `tsconfig.json`. #### options Type: `GetTsconfigOptions` ```ts type GetTsconfigOptions = { configName?: string // default: 'tsconfig.json' cache?: Map includes?: boolean // default: false } ``` - **configName**: file name to search for (e.g. `'jsconfig.json'`) - **cache**: snapshot cache for fs operations. Reusing after filesystem changes can return stale results. - **includes**: when `true`, validates the file is a root file (matched by `include`/`files` globs, not excluded) before accepting the tsconfig. Matches VS Code's Language Server behavior. Default matches `tsc` CLI behavior (nearest tsconfig). Note: this checks glob matching only — a file can still be part of a TypeScript program via transitive imports even if not matched by `include`. #### Example ```ts import { getTsconfig } from 'get-tsconfig' // Find from current directory getTsconfig() // Find from a file path getTsconfig('./src/index.ts') // Search for jsconfig.json getTsconfig('.', { configName: 'jsconfig.json' }) // Language Server behavior — validate the file is included getTsconfig('./src/index.ts', { includes: true }) ``` ### findTsconfig(searchPath?, options?) Like `getTsconfig`, but returns only the path (`string | undefined`) without parsing. Same options. ```ts import { findTsconfig } from 'get-tsconfig' findTsconfig() // → '/project/tsconfig.json' ``` ### readTsconfig(tsconfigPath, options?) Reads and resolves a tsconfig at a known path. Used internally by `getTsconfig`. ```ts type ReadTsconfigOptions = { cache?: Map } ``` ```ts import { readTsconfig } from 'get-tsconfig' const { path, config } = readTsconfig('./tsconfig.json') ``` ## Tsconfig `extends` `readTsconfig` and `getTsconfig` fully resolve the [`extends`](https://www.typescriptlang.org/tsconfig/#extends) chain and return a flattened config. These two functions expose the chain for use cases like watch mode and config auditing. ### getExtendsChain(tsconfigPath, options?) Collects the full extends chain. Returns an array of `TsconfigResult` entries — each containing the raw (unmerged) config with `extends` resolved to absolute paths. (`TsconfigJson` is the raw tsconfig.json shape, including the `extends` field.) `chain[0]` is the root. Ancestors follow in resolution order. ```ts type GetExtendsChainOptions = { cache?: Map } ``` ```ts import { getExtendsChain } from 'get-tsconfig' const chain = getExtendsChain('./tsconfig.json') // [ // { path: '/project/tsconfig.json', config: { extends: '/project/base.json', ... } }, // { path: '/project/base.json', config: { ... } }, // ] // Watch all files in the extends chain const filesToWatch = chain.map(entry => entry.path) ``` ### resolveExtendsChain(chain) Merges a collected extends chain into a resolved tsconfig. Pure function — no filesystem access. ```ts import { getExtendsChain, resolveExtendsChain } from 'get-tsconfig' const chain = getExtendsChain('./tsconfig.json') // Modify before merging chain[0].config.compilerOptions = { ...chain[0].config.compilerOptions, sourceMap: true } const result = resolveExtendsChain(chain) // TsconfigResult { path, config, sources } ``` ## Working with a tsconfig These functions take a parsed `TsconfigResult` (from `getTsconfig` or `readTsconfig`) and answer questions about it. They cache compiled state per tsconfig object — do not mutate the tsconfig after the first call. ### isFileIncluded(tsconfig, filePath) Checks whether an absolute file path matches a tsconfig's `files`, `include`, and `exclude` globs — i.e., whether it's a **root file**. Case sensitivity is auto-detected from the filesystem. Non-absolute paths return `false`. > [!NOTE] > This checks glob matching only, not transitive imports. A file outside `include` can still be part of the TypeScript program if it's imported by a root file. `exclude` only filters the initial glob matching — it doesn't prevent transitively imported files from being compiled. ```ts import { getTsconfig, isFileIncluded } from 'get-tsconfig' const tsconfig = getTsconfig() if (tsconfig && isFileIncluded(tsconfig, '/path/to/file.ts')) { // file is a root file of this tsconfig } ``` ### resolvePathAlias(tsconfig, specifier) Resolves an [import specifier](https://nodejs.org/api/esm.html#terminology) against [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths). Returns an array of possible file paths, or an empty array if no match. Does not perform actual file resolution. ```ts import { getTsconfig, resolvePathAlias } from 'get-tsconfig' const tsconfig = getTsconfig() const tryPaths = tsconfig && resolvePathAlias(tsconfig, '@/utils/helper') if (tryPaths?.length) { // Check if paths in tryPaths exist } ``` ## FAQ ### How can I use TypeScript to parse `tsconfig.json`? This package is a re-implementation of TypeScript's `tsconfig.json` parser. However, if you already have TypeScript as a dependency, you can simply use it's API: ```ts import { sys as tsSys, findConfigFile, readConfigFile, parseJsonConfigFileContent } from 'typescript' // Find tsconfig.json file const tsconfigPath = findConfigFile(process.cwd(), tsSys.fileExists, 'tsconfig.json') // Read tsconfig.json file const tsconfigFile = readConfigFile(tsconfigPath, tsSys.readFile) // Resolve extends const parsedTsconfig = parseJsonConfigFileContent( tsconfigFile.config, tsSys, path.dirname(tsconfigPath) ) ``` ## Sponsors