get-tsconfig

repository·master·Indexed 42 days ago

https://github.com/privatenumber/get-tsconfig

A zero-dependency utility for finding and parsing tsconfig.json files. It resolves configurations, including extends and file inclusion/exclusion logic, without requiring the TypeScript compiler. Features include getTsconfig(), findTsconfig(), parseTsconfig(), and utilities for creating file and path matchers.

Tokens
15.9K
Snippets
17
Records
87
Agent score
52%

What's inside get-tsconfig

  1. How the Language Service selects projects

    master

    The TypeScript Language Service follows specific rules to find configuration files:

    1. Priority: It checks for tsconfig.json before jsconfig.json while walking upward from the file location.
    2. Search Boundaries:
      • A defined project root limits the upward walk.
      • If a search starts inside a node_modules directory, the search stops after checking the node_modules directory itself.
    3. Applicability: The service uses a 'root-list-first' approach. A source file must be present in the parsed root list to be accepted. Direct files and include/exclude matching is only used as a fallback for file kinds that are otherwise unsupported.
  2. Understand `watchOptions` inheritance

    master

    The watchOptions property follows a property-by-property merge pattern:

    1. Property Merging: Later parents replace earlier parent properties, and the child replaces inherited properties.
    2. Granular Overrides: You can override a specific sub-property (like watchFile) in the child config while still inheriting other sub-properties (like watchDirectory) from the parent.
  3. How automatic type packages are resolved

    master

    The types option controls how TypeScript handles type packages:

    • When types is absent: TypeScript automatically enumerates all visible packages found beneath every effective type root.
    • When types is present: Providing an explicit types array bypasses automatic enumeration and instructs TypeScript to supply only the specified package names directly.
  4. How `findConfigFile` performs upward discovery

    master

    The findConfigFile function is used to locate a TypeScript configuration file by probing the starting directory and then traversing upwards through each parent directory. It returns the first candidate for which the fileExists check returns true and stops once it reaches the filesystem root.

    Important Constraints:

    • It only performs upward filename discovery.
    • It does not parse the candidate file.
    • It does not verify if a specific source file belongs to the candidate's root set.
    findConfigFile(searchPath, fileExists, configName = "tsconfig.json")
  5. Understand important compiler option override semantics

    master

    Certain compiler options have complex override behaviors that can lead to unexpected results if not understood:

    • Strict-family overrides: Children of strict can override the parent in either direction.
      • strict: true + strictNullChecks: false $\rightarrow$ Null checking is off.
      • strict: false + strictNullChecks: true $\rightarrow$ Null checking is on.
    • Composite projects: Setting composite: true makes declaration and incremental effective. You cannot explicitly set these to false to negate the implication; doing so is a validation error.
    • Verbatim Module Syntax: If verbatimModuleSyntax: true is set, isolatedModules becomes effectively true even if explicitly set to false. This in turn makes preserveConstEnums effectively true.
    • CheckJS and AllowJS: checkJs: true implies allowJs: true only if allowJs is absent. If you explicitly set allowJs: false, the combination is invalid.
  6. How `extends` inheritance and precedence works

    master

    TypeScript 6.0.3 follows these rules for multiple base configurations:

    • Precedence: Multiple bases apply from left to right. Later bases replace properties from earlier bases. The child configuration replaces all bases.
    • File Specifications: These are inherited only if the child value is absent or null. Providing an own array (even an empty one []) blocks inheritance.
    • Rebasing: Inherited file specifications are rebased to preserve their original declaring configuration.
    • Caching: The system uses extended-config caching and prevents circularity.
  7. Understand TypeScript 6.0.3 compiler option defaults

    master

    In TypeScript 6.0.3, compilerOptions in a tsconfig.json file only contains the properties explicitly provided by the user. Most other settings are 'lazy effective values'—they are computed by the compiler at runtime based on other settings or omitted values.

    Key behaviors include:

    • tsc --showConfig: This command enumerates stored properties and only adds computed options if they differ from their default computation on an empty object.
    • tsc --init: The generated template explicitly writes certain values (like NodeNext and ESNext), so they will appear in the file rather than being treated as omitted defaults.
    • Representation Boundary: An empty config file will still result in an empty compilerOptions object in the JSON, even though the compiler has many effective default settings.
  8. Understand fallback boundaries in path resolution

    master

    It is critical to understand when TypeScript stops searching for a module:

    • No Key Match: If no key in paths matches the module name, TypeScript falls back to trying a single baseUrl candidate formed from the original module name.
    • Matched Key but Failed Substitution: If a key matches but all provided substitutions in the array fail to resolve to an actual file, TypeScript stops searching the paths logic. It will not attempt to try the baseUrl candidate. Instead, the resolver moves directly to other resolution strategies like node_modules or ordinary relative resolution.
  9. How `paths` and `baseUrl` resolution order works

    master

    TypeScript follows a specific precedence when resolving module names using paths and baseUrl:

    1. paths resolution: TypeScript first attempts to match the module name against the paths configuration. This only occurs if the module name is not a dot-relative specifier (e.g., it does not start with ., .., ./, or ../).
    2. baseUrl resolution: If no paths match is found, TypeScript attempts to resolve the module name relative to the baseUrl.

    Important Note on Rooted Specifiers: A rooted specifier (an absolute disk path) can match a key in paths, but it is prevented from falling through to baseUrl resolution. If a rooted specifier matches a paths key, the search is confined to that mapping.

  10. Extended-config caching behavior

    master

    To optimize performance, TypeScript caches extended configurations.

    • Cache Keys: Configurations are cached by their exact path or lowercased path, depending on the host filesystem's case sensitivity.
    • Stored Data: The cache stores both the raw JSON source file and the parsed configuration object.
    • Error Caching: If a configuration fails to parse, the parse-diagnostic failure is also cached (stored as a source file without a parsed config) to avoid redundant failed parsing attempts.
  11. How package directories are handled

    master

    TypeScript automatically excludes common package directories from wildcard searches to improve performance and prevent accidental inclusion of dependencies.

    Recognized package directories:

    • node_modules
    • bower_components
    • jspm_packages

    How to include files from these directories

    Even though they are excluded by default, you can still include files from them using:

    1. Explicit paths: Using a literal path like **/node_modules/a.ts.
    2. Literal entries: Using an exact file path in the files array.