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

import './file.json': This module is declared with using 'export =' #37623

Open
fregante opened this issue Mar 26, 2020 · 5 comments
Open

import './file.json': This module is declared with using 'export =' #37623

fregante opened this issue Mar 26, 2020 · 5 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@fregante
Copy link

fregante commented Mar 26, 2020

In short, JSON files's implied type definition is always defined via export =, even if I'm using module: es2015, causing it to error unless I use an unnecessary flag (allowSyntheticDefaultImports)

TypeScript Version: 3.9.0-dev.20200326

Search Terms:

import require json module commonjs es2015

Code

import list from "./list.json";

for (const item of list) {
	console.log(item)
}
{
	"compilerOptions": {
		"outDir": "distribution",
		"target": "es2017",
		"module": "es2015",
		"moduleResolution": "node",
		"resolveJsonModule": true,
		"strict": true
	},
	"files": [
		"index.ts"
	]
}

Expected behavior:

list is of type string[]

Actual behavior:

index.ts:1:8 - error TS1259: Module '"./list"' can only be default-imported using the 'allowSyntheticDefaultImports' flag

1 import list from "./list.json";
         ~~~~

  list.json:1:1
    1 [
      ~
    This module is declared with using 'export =', and can only be used with a default import when using the 'allowSyntheticDefaultImports' flag.


Found 1 error.

Workaround:

  1. allowSyntheticDefaultImports: true works as expected, but that flag is unsafe and I don't want (need) to use it.
  2. declare module './list.json' {
    	const list: string[];
    	export default list;
    }

Playground Link: repro.zip

Related Issues: #15146

@fregante
Copy link
Author

I also tried:

import * as list from './list.json;

While that works, it shouldn't. list isn't an iterable at all in this case, and it's a runtime error.

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Mar 27, 2020

What module loaders present JSON objects via the default export instead of top-level export? Or does the file look like

{
  "default": (something)
}

?

@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Mar 27, 2020
@fregante
Copy link
Author

fregante commented Mar 27, 2020

I had to do some research:

  • The spec doesn't seem to support loading JSON files yet, can't find any mentions of it
  • Firefox 74 errors out with:

    Loading module from “./package.json” was blocked because of a disallowed MIME type (“application/json”)

  • Node 13 supports it experimentally

    When the --experimental-json-modules flag is included both the commonjs and module mode will use the new experimental JSON loader. The imported JSON only exposes a default, there is no support for named exports.

    import packageConfig from './package.json';
    Sadly the WHATWG link in Node's docs is a gone from the spec
  • Rollup supports it with a plugin
    import pkg from './package.json';
    console.log(`running version ${pkg.version}`);
  • Webpack maps it to a require, so import list from './list.json works as expected
  • Browserify doesn't support ES Modules, but I assume that the esm module does what Webpack does.

Ultimately, I think that TypeScript’s behavior is correct since import './file.json' is technically invalid, even though experimentally supported in some places.

The right flag to enable support (at the moment) seems to be allowSyntheticDefaultImports — it makes TS work and it generates invalid code, as expected.

@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus Suggestion An idea for TypeScript and removed Needs More Info The issue still hasn't been fully clarified labels Mar 27, 2020
@hn3000
Copy link
Contributor

hn3000 commented Oct 6, 2020

Since both Webpack and node import without the * as x (and for good reasons, seemingly webpack/webpack#8504 (comment)) would it make sense to provide an option for resolveJsonModule to support the same semantics?

It's very sad that we have to stick with target=es5 in order to profit from the auto completion support for imported json files when using webpack.

@teppeis
Copy link

teppeis commented Jan 26, 2021

In ECMAScript, importing JSON will be implemented with JSON modules (stage 2) based on Import Assertions (stage 3).

import json from "./foo.json" assert { type: "json" };
import("foo.json", { assert: { type: "json" } });

In TypeScript: Implement Import Assertions (stage 3) · Issue #40694 · microsoft/TypeScript

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants