Module path resolution functionality for resolving import specifiers using TypeScript's path mapping configuration from compilerOptions.paths and baseUrl.
Creates a path matcher function that resolves module specifiers according to TypeScript's path mapping rules.
/**
* Creates a path matcher function based on tsconfig paths configuration
* @param tsconfig - The parsed tsconfig result from getTsconfig or parseTsconfig
* @returns Path matcher function or null if no paths/baseUrl configuration exists
*/
function createPathsMatcher(
tsconfig: TsConfigResult
): ((specifier: string) => string[]) | null;
/**
* Function that resolves a module specifier to possible file paths
* @param specifier - The import specifier to resolve (e.g., "@/utils", "lodash")
* @returns Array of possible absolute file paths to check, empty if no matches
*/
type PathsMatcher = (specifier: string) => string[];Usage Examples:
import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";
const tsconfig = getTsconfig("./my-project");
const pathsMatcher = createPathsMatcher(tsconfig);
if (pathsMatcher) {
// Resolve path-mapped imports
const utilsPaths = pathsMatcher("@/utils"); // ["/project/src/utils"]
const componentPaths = pathsMatcher("@/components/Button"); // ["/project/src/components/Button"]
// Relative imports return empty array (handled by normal resolution)
const relativePaths = pathsMatcher("./local-file"); // []
// Non-matching specifiers fall back to baseUrl resolution
const basePaths = pathsMatcher("some-module"); // ["/project/src/some-module"] if baseUrl is set
}Path resolution works with TypeScript's compilerOptions.paths and compilerOptions.baseUrl settings:
// Example tsconfig.json with path mapping
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/*": ["./utils/*", "./lib/*"],
"@components/*": ["./components/*"],
"~/*": ["../shared/*"]
}
}
}The path matcher implements TypeScript's module resolution logic:
* wildcards, preferring longer prefixesPattern Matching Rules:
* wildcard* wildcard// Given tsconfig paths configuration:
// "@lib/*": ["./libraries/*", "./vendor/*"]
const pathsMatcher = createPathsMatcher(tsconfig);
// Resolves "@lib/utils" to:
const paths = pathsMatcher("@lib/utils");
// Returns: ["/project/src/libraries/utils", "/project/src/vendor/utils"]
// The "*" in the pattern matches "utils"
// The "*" in substitutions is replaced with "utils"When no path patterns match, baseUrl provides fallback resolution:
// Given tsconfig with baseUrl: "./src" and no matching paths
const pathsMatcher = createPathsMatcher(tsconfig);
// Non-relative specifier with baseUrl fallback
const paths = pathsMatcher("helpers/format");
// Returns: ["/project/src/helpers/format"]Common integration pattern with custom module resolution systems:
import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";
import { existsSync } from "fs";
import { resolve } from "path";
function resolveModule(specifier: string, fromFile: string): string | null {
const tsconfig = getTsconfig(fromFile);
const pathsMatcher = createPathsMatcher(tsconfig);
if (pathsMatcher) {
const candidatePaths = pathsMatcher(specifier);
// Try each candidate path with common extensions
for (const candidatePath of candidatePaths) {
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.d.ts'];
for (const ext of extensions) {
const fullPath = candidatePath + ext;
if (existsSync(fullPath)) {
return fullPath;
}
}
// Try index files
const indexPath = resolve(candidatePath, 'index.ts');
if (existsSync(indexPath)) {
return indexPath;
}
}
}
// Fallback to standard Node.js resolution
return null;
}get-tsconfig handles TypeScript's implicit baseUrl behavior when paths are specified without baseUrl:
// tsconfig.json with paths but no explicit baseUrl
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}The library automatically uses the tsconfig directory as an implicit baseUrl for path resolution.
The path matcher handles various edge cases gracefully:
null if no paths or baseUrl are configuredimport { createPathsMatcher } from "get-tsconfig";
const pathsMatcher = createPathsMatcher(tsconfig);
if (pathsMatcher === null) {
console.log("No path mapping configuration found");
} else {
// Safe to use path matcher
const paths = pathsMatcher("@/utils");
}Example integration with bundlers and build tools:
import { getTsconfig, createPathsMatcher, type TsConfigResult } from "get-tsconfig";
function createResolver(projectRoot: string) {
const tsconfig = getTsconfig(projectRoot);
const pathsMatcher = createPathsMatcher(tsconfig);
return {
resolve(specifier: string, importer: string): string[] {
if (pathsMatcher) {
const mappedPaths = pathsMatcher(specifier);
if (mappedPaths.length > 0) {
return mappedPaths;
}
}
// Fallback to standard resolution
return [specifier];
}
};
}