Skip to content

Commit 9bf5aa7

Browse files
authored
Do not require import attributes for JSON imports in --module node16 (#60673)
1 parent 6f75783 commit 9bf5aa7

8 files changed

+304
-14
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48100,7 +48100,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4810048100
}
4810148101
}
4810248102

48103-
if (isOnlyImportableAsDefault(node.moduleSpecifier, resolvedModule) && !hasTypeJsonImportAttribute(node)) {
48103+
if (moduleKind === ModuleKind.NodeNext && isOnlyImportableAsDefault(node.moduleSpecifier, resolvedModule) && !hasTypeJsonImportAttribute(node)) {
48104+
// Import attributes/assertions are not allowed in --module node16, so don't suggest adding one
4810448105
error(node.moduleSpecifier, Diagnostics.Importing_a_JSON_file_into_an_ECMAScript_module_requires_a_type_Colon_json_import_attribute_when_module_is_set_to_0, ModuleKind[moduleKind]);
4810548106
}
4810648107
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/loosey.cts(1,36): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
2+
/loosey.cts(6,9): error TS2339: Property 'default' does not exist on type '{ version: number; }'.
3+
/main.mts(5,36): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
4+
/main.mts(6,52): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
5+
/main.mts(8,10): error TS1544: Named imports from a JSON file into an ECMAScript module are not allowed when 'module' is set to 'Node16'.
6+
/main.mts(8,41): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
7+
/main.mts(9,42): error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
8+
/main.mts(10,9): error TS2339: Property 'version' does not exist on type '{ default: { version: number; }; }'.
9+
10+
11+
==== /node_modules/not.json/package.json (0 errors) ====
12+
{
13+
"name": "not.json",
14+
"version": "1.0.0",
15+
"type": "module",
16+
"exports": "./index.js"
17+
}
18+
19+
==== /node_modules/not.json/index.d.ts (0 errors) ====
20+
export function oops(json: string): any;
21+
22+
==== /node_modules/actually-json/package.json (0 errors) ====
23+
{
24+
"name": "actually-json",
25+
"version": "1.0.0",
26+
"type": "module",
27+
"exports": {
28+
".": "./index.json",
29+
"./typed": "./typed.d.json.ts"
30+
}
31+
}
32+
33+
==== /node_modules/actually-json/index.json (0 errors) ====
34+
{}
35+
36+
==== /node_modules/actually-json/typed.d.json.ts (0 errors) ====
37+
declare const _default: {};
38+
export default _default;
39+
40+
==== /config.json (0 errors) ====
41+
{
42+
"version": 1
43+
}
44+
45+
==== /main.mts (6 errors) ====
46+
import { oops } from "not.json"; // Ok
47+
import moreOops from "actually-json"; // Error in nodenext
48+
import typed from "actually-json/typed"; // Error in nodenext
49+
50+
import config from "./config.json" with { type: "json" }; // Ok
51+
~~~~~~~~~~~~~~~~~~~~~
52+
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
53+
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
54+
~~~~~~~~~~~~~~~~~~~~~
55+
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
56+
import config2 from "./config.json"; // Error in nodenext, no attribute
57+
import { version } from "./config.json" with { type: "json" }; // Error, named import
58+
~~~~~~~
59+
!!! error TS1544: Named imports from a JSON file into an ECMAScript module are not allowed when 'module' is set to 'Node16'.
60+
~~~~~~~~~~~~~~~~~~~~~
61+
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
62+
import * as config3 from "./config.json" with { type: "json" };
63+
~~~~~~~~~~~~~~~~~~~~~
64+
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
65+
config3.version; // Error
66+
~~~~~~~
67+
!!! error TS2339: Property 'version' does not exist on type '{ default: { version: number; }; }'.
68+
config3.default; // Ok
69+
70+
==== /loosey.cts (2 errors) ====
71+
import config from "./config.json" with { type: "json" }; // Error
72+
~~~~~~~~~~~~~~~~~~~~~
73+
!!! error TS2823: Import attributes are only supported when the '--module' option is set to 'esnext', 'nodenext', or 'preserve'.
74+
import config2 from "./config.json"; // Ok
75+
import { version } from "./config.json"; // Ok
76+
import * as config3 from "./config.json";
77+
config3.version; // Ok
78+
config3.default; // Error
79+
~~~~~~~
80+
!!! error TS2339: Property 'default' does not exist on type '{ version: number; }'.
81+

tests/baselines/reference/nodeModulesJson.symbols renamed to tests/baselines/reference/nodeModulesJson(module=node16).symbols

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ export default _default;
2626
import { oops } from "not.json"; // Ok
2727
>oops : Symbol(oops, Decl(main.mts, 0, 8))
2828

29-
import moreOops from "actually-json"; // Error
29+
import moreOops from "actually-json"; // Error in nodenext
3030
>moreOops : Symbol(moreOops, Decl(main.mts, 1, 6))
3131

32-
import typed from "actually-json/typed"; // Error
32+
import typed from "actually-json/typed"; // Error in nodenext
3333
>typed : Symbol(typed, Decl(main.mts, 2, 6))
3434

3535
import config from "./config.json" with { type: "json" }; // Ok
@@ -39,7 +39,7 @@ import { default as config1 } from "./config.json" with { type: "json" }; // Ok
3939
>default : Symbol(config, Decl(config.json, 0, 0))
4040
>config1 : Symbol(config1, Decl(main.mts, 5, 8))
4141

42-
import config2 from "./config.json"; // Error, no attribute
42+
import config2 from "./config.json"; // Error in nodenext, no attribute
4343
>config2 : Symbol(config2, Decl(main.mts, 6, 6))
4444

4545
import { version } from "./config.json" with { type: "json" }; // Error, named import

tests/baselines/reference/nodeModulesJson.types renamed to tests/baselines/reference/nodeModulesJson(module=node16).types

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ import { oops } from "not.json"; // Ok
3838
>oops : (json: string) => any
3939
> : ^ ^^ ^^^^^
4040

41-
import moreOops from "actually-json"; // Error
41+
import moreOops from "actually-json"; // Error in nodenext
4242
>moreOops : {}
4343
> : ^^
4444

45-
import typed from "actually-json/typed"; // Error
45+
import typed from "actually-json/typed"; // Error in nodenext
4646
>typed : typeof typed
4747
> : ^^^^^^^^^^^^
4848

@@ -60,7 +60,7 @@ import { default as config1 } from "./config.json" with { type: "json" }; // Ok
6060
>type : any
6161
> : ^^^
6262

63-
import config2 from "./config.json"; // Error, no attribute
63+
import config2 from "./config.json"; // Error in nodenext, no attribute
6464
>config2 : { version: number; }
6565
> : ^^^^^^^^^^^^^^^^^^^^
6666

tests/baselines/reference/nodeModulesJson.errors.txt renamed to tests/baselines/reference/nodeModulesJson(module=nodenext).errors.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@
4343

4444
==== /main.mts (5 errors) ====
4545
import { oops } from "not.json"; // Ok
46-
import moreOops from "actually-json"; // Error
46+
import moreOops from "actually-json"; // Error in nodenext
4747
~~~~~~~~~~~~~~~
4848
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
49-
import typed from "actually-json/typed"; // Error
49+
import typed from "actually-json/typed"; // Error in nodenext
5050
~~~~~~~~~~~~~~~~~~~~~
5151
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
5252

5353
import config from "./config.json" with { type: "json" }; // Ok
5454
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
55-
import config2 from "./config.json"; // Error, no attribute
55+
import config2 from "./config.json"; // Error in nodenext, no attribute
5656
~~~~~~~~~~~~~~~
5757
!!! error TS1543: Importing a JSON file into an ECMAScript module requires a 'type: "json"' import attribute when 'module' is set to 'NodeNext'.
5858
import { version } from "./config.json" with { type: "json" }; // Error, named import
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//// [tests/cases/conformance/node/nodeModulesJson.ts] ////
2+
3+
=== /node_modules/not.json/index.d.ts ===
4+
export function oops(json: string): any;
5+
>oops : Symbol(oops, Decl(index.d.ts, 0, 0))
6+
>json : Symbol(json, Decl(index.d.ts, 0, 21))
7+
8+
=== /node_modules/actually-json/index.json ===
9+
10+
{}
11+
12+
=== /node_modules/actually-json/typed.d.json.ts ===
13+
declare const _default: {};
14+
>_default : Symbol(_default, Decl(typed.d.json.ts, 0, 13))
15+
16+
export default _default;
17+
>_default : Symbol(_default, Decl(typed.d.json.ts, 0, 13))
18+
19+
=== /config.json ===
20+
{
21+
"version": 1
22+
>"version" : Symbol("version", Decl(config.json, 0, 1))
23+
}
24+
25+
=== /main.mts ===
26+
import { oops } from "not.json"; // Ok
27+
>oops : Symbol(oops, Decl(main.mts, 0, 8))
28+
29+
import moreOops from "actually-json"; // Error in nodenext
30+
>moreOops : Symbol(moreOops, Decl(main.mts, 1, 6))
31+
32+
import typed from "actually-json/typed"; // Error in nodenext
33+
>typed : Symbol(typed, Decl(main.mts, 2, 6))
34+
35+
import config from "./config.json" with { type: "json" }; // Ok
36+
>config : Symbol(config, Decl(main.mts, 4, 6))
37+
38+
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
39+
>default : Symbol(config, Decl(config.json, 0, 0))
40+
>config1 : Symbol(config1, Decl(main.mts, 5, 8))
41+
42+
import config2 from "./config.json"; // Error in nodenext, no attribute
43+
>config2 : Symbol(config2, Decl(main.mts, 6, 6))
44+
45+
import { version } from "./config.json" with { type: "json" }; // Error, named import
46+
>version : Symbol(version, Decl(main.mts, 7, 8))
47+
48+
import * as config3 from "./config.json" with { type: "json" };
49+
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
50+
51+
config3.version; // Error
52+
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
53+
54+
config3.default; // Ok
55+
>config3.default : Symbol("/config")
56+
>config3 : Symbol(config3, Decl(main.mts, 8, 6))
57+
>default : Symbol("/config")
58+
59+
=== /loosey.cts ===
60+
import config from "./config.json" with { type: "json" }; // Error
61+
>config : Symbol(config, Decl(loosey.cts, 0, 6))
62+
63+
import config2 from "./config.json"; // Ok
64+
>config2 : Symbol(config2, Decl(loosey.cts, 1, 6))
65+
66+
import { version } from "./config.json"; // Ok
67+
>version : Symbol(version, Decl(loosey.cts, 2, 8))
68+
69+
import * as config3 from "./config.json";
70+
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
71+
72+
config3.version; // Ok
73+
>config3.version : Symbol(version, Decl(config.json, 0, 1))
74+
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
75+
>version : Symbol(version, Decl(config.json, 0, 1))
76+
77+
config3.default; // Error
78+
>config3 : Symbol(config3, Decl(loosey.cts, 3, 6))
79+
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//// [tests/cases/conformance/node/nodeModulesJson.ts] ////
2+
3+
=== /node_modules/not.json/index.d.ts ===
4+
export function oops(json: string): any;
5+
>oops : (json: string) => any
6+
> : ^ ^^ ^^^^^
7+
>json : string
8+
> : ^^^^^^
9+
10+
=== /node_modules/actually-json/index.json ===
11+
{}
12+
>{} : {}
13+
> : ^^
14+
15+
=== /node_modules/actually-json/typed.d.json.ts ===
16+
declare const _default: {};
17+
>_default : {}
18+
> : ^^
19+
20+
export default _default;
21+
>_default : {}
22+
> : ^^
23+
24+
=== /config.json ===
25+
{
26+
>{ "version": 1} : { version: number; }
27+
> : ^^^^^^^^^^^^^^^^^^^^
28+
29+
"version": 1
30+
>"version" : number
31+
> : ^^^^^^
32+
>1 : 1
33+
> : ^
34+
}
35+
36+
=== /main.mts ===
37+
import { oops } from "not.json"; // Ok
38+
>oops : (json: string) => any
39+
> : ^ ^^ ^^^^^
40+
41+
import moreOops from "actually-json"; // Error in nodenext
42+
>moreOops : {}
43+
> : ^^
44+
45+
import typed from "actually-json/typed"; // Error in nodenext
46+
>typed : typeof typed
47+
> : ^^^^^^^^^^^^
48+
49+
import config from "./config.json" with { type: "json" }; // Ok
50+
>config : { version: number; }
51+
> : ^^^^^^^^^^^^^^^^^^^^
52+
>type : any
53+
> : ^^^
54+
55+
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
56+
>default : { version: number; }
57+
> : ^^^^^^^^^^^^^^^^^^^^
58+
>config1 : { version: number; }
59+
> : ^^^^^^^^^^^^^^^^^^^^
60+
>type : any
61+
> : ^^^
62+
63+
import config2 from "./config.json"; // Error in nodenext, no attribute
64+
>config2 : { version: number; }
65+
> : ^^^^^^^^^^^^^^^^^^^^
66+
67+
import { version } from "./config.json" with { type: "json" }; // Error, named import
68+
>version : number
69+
> : ^^^^^^
70+
>type : any
71+
> : ^^^
72+
73+
import * as config3 from "./config.json" with { type: "json" };
74+
>config3 : { default: { version: number; }; }
75+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76+
>type : any
77+
> : ^^^
78+
79+
config3.version; // Error
80+
>config3.version : any
81+
> : ^^^
82+
>config3 : { default: { version: number; }; }
83+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
>version : any
85+
> : ^^^
86+
87+
config3.default; // Ok
88+
>config3.default : { version: number; }
89+
> : ^^^^^^^^^^^^^^^^^^^^
90+
>config3 : { default: { version: number; }; }
91+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92+
>default : { version: number; }
93+
> : ^^^^^^^^^^^^^^^^^^^^
94+
95+
=== /loosey.cts ===
96+
import config from "./config.json" with { type: "json" }; // Error
97+
>config : { version: number; }
98+
> : ^^^^^^^^^^^^^^^^^^^^
99+
>type : any
100+
> : ^^^
101+
102+
import config2 from "./config.json"; // Ok
103+
>config2 : { version: number; }
104+
> : ^^^^^^^^^^^^^^^^^^^^
105+
106+
import { version } from "./config.json"; // Ok
107+
>version : number
108+
> : ^^^^^^
109+
110+
import * as config3 from "./config.json";
111+
>config3 : { version: number; }
112+
> : ^^^^^^^^^^^^^^^^^^^^
113+
114+
config3.version; // Ok
115+
>config3.version : number
116+
> : ^^^^^^
117+
>config3 : { version: number; }
118+
> : ^^^^^^^^^^^^^^^^^^^^
119+
>version : number
120+
> : ^^^^^^
121+
122+
config3.default; // Error
123+
>config3.default : any
124+
> : ^^^
125+
>config3 : { version: number; }
126+
> : ^^^^^^^^^^^^^^^^^^^^
127+
>default : any
128+
> : ^^^
129+

tests/cases/conformance/node/nodeModulesJson.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @module: nodenext
1+
// @module: node16,nodenext
22
// @resolveJsonModule: true
33
// @noEmit: true
44

@@ -38,12 +38,12 @@ export default _default;
3838

3939
// @Filename: /main.mts
4040
import { oops } from "not.json"; // Ok
41-
import moreOops from "actually-json"; // Error
42-
import typed from "actually-json/typed"; // Error
41+
import moreOops from "actually-json"; // Error in nodenext
42+
import typed from "actually-json/typed"; // Error in nodenext
4343

4444
import config from "./config.json" with { type: "json" }; // Ok
4545
import { default as config1 } from "./config.json" with { type: "json" }; // Ok
46-
import config2 from "./config.json"; // Error, no attribute
46+
import config2 from "./config.json"; // Error in nodenext, no attribute
4747
import { version } from "./config.json" with { type: "json" }; // Error, named import
4848
import * as config3 from "./config.json" with { type: "json" };
4949
config3.version; // Error

0 commit comments

Comments
 (0)