Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reexported types are emitted in js files #38647

Closed
HitalloExiled opened this issue May 18, 2020 · 6 comments
Closed

Reexported types are emitted in js files #38647

HitalloExiled opened this issue May 18, 2020 · 6 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@HitalloExiled
Copy link

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;
@weswigham
Copy link
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
Copy link

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
Copy link
Author

@stephenzsy
Or something like:

export type * from "types"

Since this is supported:

export type { MyType } from "types"

@stephenzsy
Copy link

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

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 8, 2020
@typescript-bot
Copy link
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
Copy link

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
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

6 participants