Skip to content

Add template variable ${configDir} (name to be determined) for file path substitutionย #57485

Closed

Description

๐Ÿ” Search Terms

"extends", "compilerOptions", "paths", "outdir", "include", "exclude", "typeRoots", "tsconfig", "ability to make tsconfig paths relative to final config"

โœ… Viability Checklist

โญ Suggestion

Subset of #56436

Today when all the options that are file paths, are always relative to config they are specified in. But that also means that if you are extending tsconfig and you want eg say outDir to be same name but relative to your config, you have to re-specify it in the config. The proposal is to use template variable in base config which would mean that the resulting file paths are relative to final config directory. Name is to be determined.

Consider:

// @fileName: /temp/test/base.tsconfig.json
{
    "compilerOptions": {
        "typeRoots": ["node_modules/@types"],
        "outDir": "dist"
    }
}
// @fileName: /temp/test/project1/tsconfig.json
{
    "extends": "../base.tsconfig.json"
}

Today the resulting config of project1 is:

// @fileName: /temp/test/project1/computed.tsconfig.json
{
    "compilerOptions": {
        "typeRoots": ["../node_modules/@types"],
        "outDir": "../dist"
    }
}

Proposal is to write base.tsconfig.json as:

// @fileName: /temp/test/base.tsconfig.json
{
    "compilerOptions": {
        "typeRoots": ["${configDir}/node_modules/@types"],
        "outDir": "${configDir}/dist"
    }
}

and this should result in computed tsconfig.json as:

// @fileName: /temp/test/project1/computed.tsconfig.json
{
    "compilerOptions": {
        "typeRoots": ["./node_modules/@types"],
        "outDir": "./dist"
    }
}

Names that came up in design meeting:

  • configLocation
  • configFolder
  • configDirectory
  • projectLocation
  • projectFolder
  • projectDirectory

๐Ÿ“ƒ Motivating Example

A way to specify root config that can specify include and/or outDir and not needing to write than in each project.
Issues: #29172, #30163, #37227, #45050, #51213

๐Ÿ’ป Use Cases

  1. What do you want to use this for?
  2. What shortcomings exist with current approaches?
  3. What workarounds are you using in the meantime?

Activity

  1. sheetalkamat commented on Mar 29, 2024

    @sheetalkamat
    MemberAuthor

    Options that should check for ${configDir}
    Some of these options can be passed on commandline. Do we allow passing ${configDir} in them

    Option Category Option Type isFilePath
    CompilerOptions outDir string true
    CompilerOptions declarationDir string true
    CompilerOptions outFile string true
    CompilerOptions rootDir string true
    CompilerOptions baseUrl string true
    CompilerOptions tsBuildInfoFile string true
    CompilerOptions rootDirs string[] true
    CompilerOptions typeRoots string[] true
    CompilerOptions paths object false values need to be lookedup and substituted
    WatchOptions excludeFiles string[] true
    WatchOptions excludeDirectories string[] true
    Root files string[] false
    Root include string[] false
    Root exclude string[] false

    Options that are of type string or object but should not check ${configDir}

    Option Category Option Type isFilePath
    CompilerOptions types string[] false
    CompilerOptions moduleSuffixes string[] false
    CompilerOptions customConditions string[] false
    CompilerOptions sourceRoot string false we use value as is
    CompilerOptions mapRoot string false we use value as is
    CompilerOptions jsxFactory string false
    CompilerOptions jsxFragmentFactory string false
    CompilerOptions jsxImportSource string false
    CompilerOptions out string false deprecated and suppose to be used as is
    CompilerOptions ignoreDeprecations string false
    CompilerOptions reactNamespace string false
    CompilerOptions charset string false
    CompilerOptions plugins object false should not map names as we dont allow relative module names
    CompilerOptions project string true Commandline only
    CompilerOptions generateCpuProfile string true Commandline only, if commandline ${configDir} is allowed is this ok to pass?
    CompilerOptions generateTrace string true Commandline only, if commandline ${configDir} is allowed is this ok to pass?
    CompilerOptions locale string false Commandline only
    TypeAcquisition include string[] false
    TypeAcquisition exclude string[] false
    Root extends string or string[] false this is directly in the config so no point of having ${configDir}
    Root references object false references are not inherited, so no need of substitution
  2. Bessonov commented on Apr 17, 2024

    @Bessonov

    Thank you, Sheetal Nandi (@sheetalkamat), you are amazing!

  3. karlhorky commented on Apr 19, 2024

    @karlhorky
    Contributor

    Sheetal Nandi (@sheetalkamat) Awesome job, thanks! ๐ŸŽ‰ looking forward to having this released in a TypeScript version for my shared tsconfigs ๐Ÿ˜

    Is it planned that this will be released in TypeScript 5.5? I didn't see it in the Iteration Plan:

  4. D4N14L commented on Apr 19, 2024

    @D4N14L

    Sheetal Nandi (@sheetalkamat) thank you! This has been a feature I've wanted to see for some time now. Great to finally have it!

  5. karlhorky commented on Apr 29, 2024

    @karlhorky
    Contributor

    Is it planned that this will be released in TypeScript 5.5? I didn't see it in the Iteration Plan

    Looks like will be a part of TS 5.5 (or at least is in the 5.5 Beta announcement):

  6. simonhaenisch commented on May 8, 2024

    @simonhaenisch

    Nice, I've just tried this out yesterday and it works like a charm.

    Only issue I had was that somehow Intellisense in VS Code still showed me an error in the editor which wasn't actually a build error, like it doesn't understand the ${configDir} variable yet.

    // base.json
    {
      // ...
      "include": ["some-file.d.ts", "${configDir}/src"]
    }
    // some/path/tsconfig.json
    {
      "extends": "../../base.json"
    }

    โ˜๏ธ this gave me the error so i tried moving the include into the composite project's tsconfig.json and that worked:

    // some/path/tsconfig.json
    {
      "extends": "../../base.json",
      "include": ["../../some-file.d.ts", "src"]
    }

    but then I tried using ${configDir} there as well and that didn't work either (thus the assumption that the var breaks it):

    // some/path/tsconfig.json
    {
      "extends": "../../base.json",
      "include": ["${configDir}/../../some-file.d.ts", "src"]
    }

    As I already said, it's only an error shown in the IDE (I did switch the workspace to use the project's typescript instead of the built-in one), running tsc works fine.

    Maybe I'll just have to wait for VS Code to update the built-in TypeScript version once 5.5 is officially published (:

  7. ChurroC commented on May 11, 2024

    @ChurroC

    Nice, I've just tried this out yesterday and it works like a charm.

    Only issue I had was that somehow Intellisense in VS Code still showed me an error in the editor which wasn't actually a build error, like it doesn't understand the ${configDir} variable yet.

    // base.json
    {
      // ...
      "include": ["some-file.d.ts", "${configDir}/src"]
    }
    // some/path/tsconfig.json
    {
      "extends": "../../base.json"
    }

    โ˜๏ธ this gave me the error so i tried moving the include into the composite project's tsconfig.json and that worked:

    // some/path/tsconfig.json
    {
      "extends": "../../base.json",
      "include": ["../../some-file.d.ts", "src"]
    }

    but then I tried using ${configDir} there as well and that didn't work either (thus the assumption that the var breaks it):

    // some/path/tsconfig.json
    {
      "extends": "../../base.json",
      "include": ["${configDir}/../../some-file.d.ts", "src"]
    }

    As I already said, it's only an error shown in the IDE (I did switch the workspace to use the project's typescript instead of the built-in one), running tsc works fine.

    Maybe I'll just have to wait for VS Code to update the built-in TypeScript version once 5.5 is officially published (:

    You can go to a ts file then on the bottom right you can see a typescript button. If you press it you can select vs code ts version and set it to the projects version. If you downloaded the 5.5.0-beta from npm vs code could be set to use that type.

  8. simonhaenisch commented on May 13, 2024

    @simonhaenisch

    ChurroC (@ChurroC)

    I did switch the workspace to use the project's typescript instead of the built-in one

    maybe you overlooked this?

    Edit: anyway you're right. Even though I had done this before via command palette which created

    {
      "typescript.tsdk": "node_modules/typescript/lib"
    }

    in the project's .vscode/settings.json (which I also committed), somehow it wasn't working anymore after restarting VS Code. I just manually switched the version again and now it's working as expected. ๐Ÿคท๐Ÿปโ€โ™‚๏ธ

  9. jakearchibald commented on Sep 10, 2024

    @jakearchibald
  10. mconnor commented on Jan 16, 2025

    @mconnor

    I have a nextjs app set up in a monorepo and using this ${configDir} feature. The the tsconfig package has:
    // some/path/tsconfig.json

    {
      ...
    "extends": "@repo/typescript-config/nextjs.json",
    "include": [
        "../../packages/typescript-config/**/*.ts",
        "../../packages/typescript-config/**/*.tsx",
        "${configDir}/.next/types/**/*.ts",
        ".next/types/**/*.ts"
      ]
    }
    

    Upon running next dev --turbopack, the tsconfig.json in the next app gets altered.
    An include gets added .. which makes no sense. There are no .ts or .tsx files in packages/typescript-config

    {
     "include": [
        "../../packages/typescript-config/**/*.ts",
        "../../packages/typescript-config/**/*.tsx",
        "${configDir}/.next/types/**/*.ts",
        ".next/types/**/*.ts"
      ]
    }
    
  11. ArifRabbaniIn commented on Aug 17, 2025

    @ArifRabbaniIn

    I have a nextjs app set up in a monorepo and using this ${configDir} feature. The the tsconfig package has: // some/path/tsconfig.json

    {
      ...
    "extends": "@repo/typescript-config/nextjs.json",
    "include": [
        "../../packages/typescript-config/**/*.ts",
        "../../packages/typescript-config/**/*.tsx",
        "${configDir}/.next/types/**/*.ts",
        ".next/types/**/*.ts"
      ]
    }
    

    Upon running next dev --turbopack, the tsconfig.json in the next app gets altered. An include gets added .. which makes no sense. There are no .ts or .tsx files in packages/typescript-config

    {
     "include": [
        "../../packages/typescript-config/**/*.ts",
        "../../packages/typescript-config/**/*.tsx",
        "${configDir}/.next/types/**/*.ts",
        ".next/types/**/*.ts"
      ]
    }
    

    Same is happening for me as well

  12. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions