'TypeScript Appends export {} to end of file in TypeScript 4 but not TypeScript 3

I have an iife that I would like to compile and I import statement for types. In TypeScript version 3.* it compiles correctly. But in TypeScript version 4.* it appends an export {}. Is there a way to prevent that?

Here is the typescript file test.ts:

import { Tester } from "./tester"

(async function test() : Promise<Tester> { return { hello: "export" } }())

tester.d.ts

export interface Tester {
    hello: string
}

Resulting file with TypeScript 4.* test.js

(async function test() { return { hello: "export" }; }());
export {};

Resulting file with TypeScript 3.9.* test.js

(async function test() { return { hello: "export" }; }());

My tsconfig.json file:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ES2015",
    "moduleResolution": "Node",

    "strict": true,
    "noImplicitAny": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "allowJs": true,

    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    "outDir": "./public/app",
    "skipLibCheck": true
  },
  "compileOnSave": true,"src/app/meals/add/index.template.js", "src/app/utils/html-template-tag.js" ],
  "include": ["src/**/*.ts", "src/**/*.js"],
  "exclude": [
    "node_modules", "src/**/*spec.ts"
  ]
}

The command I use for it:

tsc -p ./tsconfig.json

Update

I added this bug report to TypeScript.

https://github.com/microsoft/TypeScript/issues/41513



Solution 1:[1]

Installed VS 16.8 which now comes with TypeScript 4. Broke my project. Added Nuget for TypeScript 3.9 to project as a workaround.

Solution 2:[2]

Somehow, I am not getting this issue with TypeScript v4.4.5. If you'd like to try with my tsconfig.json configs. Of course you will, but make sure to change the path in include

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "checkJs": true,
        "declaration": true,
        "outDir": "./",
        "rootDir": "./",
        "removeComments": true,
        "strict": true,
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    },
    "include": ["./src"],
    "exclude": ["node_modules"]
}

Once I run tsc in any file that has a module.exports, the .js file that is generated does not have an automatically added export {}.

I have attached a screenshot as well, for reference.

On the left is my route.ts file, and on right is the route.js file after running tsc

Solution 3:[3]

Here's my current work around. I just watch the output files and delete the export:

remove-emptyExport.ps1

param([string] $Path)

$stream = [IO.File]::Open($Path, [IO.FileMode]::Open)
$stream.Position = $stream.Length - 12
$bytes = 0..12 | % { $stream.ReadByte() }
if ("$bytes" -eq "101 120 112 111 114 116 32 123 125 59 13 10 -1") {
    $stream.SetLength($stream.Length - 12)
    Write-Host "Removed from $Path"
}
$stream.Close()
$stream.Dispose()

watch-files.ps1

param([string][alias("d")] $Directory, [switch][alias("w")] $Watch, [switch] $Watching)

if (!$Watching) {
    $root = (Get-Location).Path
    $Directory = Join-Path -Path $root $Directory
}

if ($Watch -and !$Watching) {
    pwsh -NoExit -File $PSCommandPath -d $Directory -Watching
    return
}

$removeExportPath = Join-Path -Path $PSScriptRoot "remove-emptyExport.ps1"

Get-ChildItem -Path $Directory -Filter *.js -Recurse | ForEach-Object {
    Invoke-Expression "$removeExportPath -Path $_"
}

Write-Host "Watching directory $Directory"

$filewatcher = New-Object System.IO.FileSystemWatcher
$filewatcher.Path = $Directory
$filewatcher.Filter = "*.js"
$filewatcher.IncludeSubdirectories = $true
$filewatcher.EnableRaisingEvents = $true

$writeaction = {
    $changeType = $Event.SourceEventArgs.ChangeType
    $path = $Event.SourceEventArgs.FullPath
    Write-Host $path $changeType
    Invoke-Expression "$removeExportPath -Path $path"
}

Register-ObjectEvent $filewatcher "Created" -Action $writeaction
Register-ObjectEvent $filewatcher "Changed" -Action $writeaction

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jaco Roux
Solution 2
Solution 3 Jon49