Skip to content

Reexported types are emitted in js files #38647

@HitalloExiled

Description

@HitalloExiled

Reexported types are emitted as actual modules in js files generating runtime errors.

Problem occurs in both commonjs and esmodule.

TypeScript Version: 3.8.3

Search Terms:
Reexported types interfaces dts

Code

// types.d.ts
export type Foo = 1;
export type Bar = 2;
//--------------------------------------
// index.ts
export * from "./types"

export default 1;

tsconfig

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs", // or esmodules
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Expected behavior:
Don't emit types reexports

Actual behavior:

commonjs

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./types"), exports); // runtime error
exports.default = 1;

esnext

export * from "./types";
export default 1;

Activity

weswigham

weswigham commented on May 18, 2020

@weswigham
Member

This was a known break scheduled for 3.9. (It should have been mentioned in the release announcement). Specifically, in the case of export *, the elision was (unintentionally) type directed, based on the contents of the target - this was not a behavior babel or other transpilers could mimic (and so users transpiling with other tools already saw this behavior). In addition, the unreliable elision made execution order at runtime unpredictable, which in turn made real runtime export availability in cases where references were circular unreliable.

You should endeavor to move the types directly into the module reexporting them, if you do not actually expect a file to be present at runtime corresponding to that declaration file (the locations of module declaration files correlate to valid runtime import paths). Failing that, explicit reexports of the types in question imported via import type declarations can work as well (as elision here is syntactically determinable).

stephenzsy

stephenzsy commented on May 20, 2020

@stephenzsy

Is that possible to have a tsconfig flag to prevent emitting empty import? export * is usually used in index.ts which sometimes import .d.ts declaration files should not get emitted.

HitalloExiled

HitalloExiled commented on May 20, 2020

@HitalloExiled
Author

@stephenzsy
Or something like:

export type * from "types"

Since this is supported:

export type { MyType } from "types"
stephenzsy

stephenzsy commented on May 25, 2020

@stephenzsy

It will be great if the following suggestion #37238 can be implemented

typescript-bot

typescript-bot commented on Jun 11, 2020

@typescript-bot
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

narkowicz

narkowicz commented on Jul 2, 2020

@narkowicz

You should endeavor to move the types directly into the module reexporting them, if you do not actually expect a file to be present at runtime corresponding to that declaration file (the locations of module declaration files correlate to valid runtime import paths). Failing that, explicit reexports of the types in question imported via import type declarations can work as well (as elision here is syntactically determinable).

@weswigham as a counter example we're re-exporting types automatically generated from JSON Schema (using https://github.com/bcherny/json-schema-to-typescript). We generate multiple files, some of which include 1k+ types over 3k+ lines. It's not practical to move them into modules or use named exports.

Another vote for #37238 as a workable solution to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @narkowicz@stephenzsy@weswigham@HitalloExiled@RyanCavanaugh

        Issue actions

          Reexported types are emitted in js files · Issue #38647 · microsoft/TypeScript