Search code examples
typescriptmsbuildvisual-studio-2019tsconfig

Override tsconfig.json in a VS2019 solution/MSBuild?


I have a Visual Studio solution (not VS Code) with multiple tsconfig.json files that I want to behave differently in production.

I want to have two files (maybe more) something like:

  1. tsconfig.json default settings for this part of the solution:
{
  "compilerOptions": {
    "sourceMap": true,
    "removeComments": false,
    ...
  },
  ... lots more settings
}
  1. tsconfig.release.json override those settings to exclude comments and source maps:
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "sourceMap": false,
    "removeComments": true
  }
}

How to I tell VS2019/MSBuild to use the tsconfig.release.json override when doing a release build or publish?


Solution

  • I've found a way to do this, but it's horrible and I'd happily accept a better answer.

    tsc can take custom config file names, but you can only run it from MSBuild if you add <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> to the project file and add something else to run it.

    MSBuild can have different options for Release vs Debug, but only if it owns all the Typescript config and there are no files called tsconfig.json anywhere in the project.

    MSBuild can find any tsconfig.json at any folder depth, but can't find any other file name - tsconfig.release.json or tsconfig.debug.json are out.

    MSBuild can also change the rules for what files it includes, so the solution:

    • Move the release overrides to a folder, so tsconfig.release.json becomes releaseConfig/tsconfig.json. It now needs some relative paths to find the project:
    {
      "extends": "../tsconfig.json",
      "compilerOptions": {
        "sourceMap": false,
        "removeComments": true
      },
      "include": [ "../**/*" ]
    }
    
    • Next we need two changes to the .csproj file. First we stop this config from being picked up in non-release builds:
    <ItemGroup Condition="'$(Configuration)|$(Platform)'!='Release|AnyCPU'">
        <Content Remove="whatever\releaseConfig\tsconfig.json" />
        <None Include="whatever\releaseConfig\tsconfig.json" />
    </ItemGroup>
    
    • Finally in the release build we swap the files:
    <ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
        <Content Remove="whatever\tsconfig.json" />
        <None Include="whatever\tsconfig.json" />
        <None Remove="whatever\releaseConfig\tsconfig.json" />
    </ItemGroup>
    

    The default tsconfig.json is removed from <Content>, but needs to be <None> so the relative paths in releaseConfig\tsconfig.json to still find it.