Skip to content

Commit 8b30ff8

Browse files
authored
Merge pull request #26817 from Microsoft/resolvingJsonModuleLikeJsExportsEqual
Use widened type and non fresh type when resolving json module
2 parents 7fe0f9d + 9eb0c9a commit 8b30ff8

File tree

6 files changed

+191
-7
lines changed

6 files changed

+191
-7
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5133,7 +5133,14 @@ namespace ts {
51335133
// Handle export default expressions
51345134
if (isSourceFile(declaration)) {
51355135
const jsonSourceFile = cast(declaration, isJsonSourceFile);
5136-
return jsonSourceFile.statements.length ? checkExpression(jsonSourceFile.statements[0].expression) : emptyObjectType;
5136+
if (!jsonSourceFile.statements.length) {
5137+
return emptyObjectType;
5138+
}
5139+
const type = getWidenedLiteralType(checkExpression(jsonSourceFile.statements[0].expression));
5140+
if (type.flags & TypeFlags.Object) {
5141+
return getRegularTypeOfObjectLiteral(type);
5142+
}
5143+
return type;
51375144
}
51385145
if (declaration.kind === SyntaxKind.ExportAssignment) {
51395146
return checkExpression((<ExportAssignment>declaration).expression);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/user.js(2,7): error TS2339: Property 'b' does not exist on type '{ "a": number; }'.
2+
/user.js(5,7): error TS2322: Type '{ "a": number; }' is not assignable to type '{ b: number; }'.
3+
Property 'b' is missing in type '{ "a": number; }'.
4+
/user.js(9,7): error TS2339: Property 'b' does not exist on type '{ "a": number; }'.
5+
/user.js(12,7): error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
6+
Property 'b' is missing in type '{ a: number; }'.
7+
8+
9+
==== /user.js (4 errors) ====
10+
const json0 = require("./json.json");
11+
json0.b; // Error (good)
12+
~
13+
!!! error TS2339: Property 'b' does not exist on type '{ "a": number; }'.
14+
15+
/** @type {{ b: number }} */
16+
const json1 = require("./json.json"); // No error (bad)
17+
~~~~~
18+
!!! error TS2322: Type '{ "a": number; }' is not assignable to type '{ b: number; }'.
19+
!!! error TS2322: Property 'b' is missing in type '{ "a": number; }'.
20+
json1.b; // No error (OK since that's the type annotation)
21+
22+
const js0 = require("./js.js");
23+
json0.b; // Error (good)
24+
~
25+
!!! error TS2339: Property 'b' does not exist on type '{ "a": number; }'.
26+
27+
/** @type {{ b: number }} */
28+
const js1 = require("./js.js"); // Error (good)
29+
~~~
30+
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ b: number; }'.
31+
!!! error TS2322: Property 'b' is missing in type '{ a: number; }'.
32+
js1.b;
33+
==== /json.json (0 errors) ====
34+
{ "a": 0 }
35+
36+
==== /js.js (0 errors) ====
37+
module.exports = { a: 0 };
38+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
=== /user.js ===
2+
const json0 = require("./json.json");
3+
>json0 : Symbol(json0, Decl(user.js, 0, 5))
4+
>require : Symbol(require)
5+
>"./json.json" : Symbol("/json", Decl(json.json, 0, 0))
6+
7+
json0.b; // Error (good)
8+
>json0 : Symbol(json0, Decl(user.js, 0, 5))
9+
10+
/** @type {{ b: number }} */
11+
const json1 = require("./json.json"); // No error (bad)
12+
>json1 : Symbol(json1, Decl(user.js, 4, 5))
13+
>require : Symbol(require)
14+
>"./json.json" : Symbol("/json", Decl(json.json, 0, 0))
15+
16+
json1.b; // No error (OK since that's the type annotation)
17+
>json1.b : Symbol(b, Decl(user.js, 3, 12))
18+
>json1 : Symbol(json1, Decl(user.js, 4, 5))
19+
>b : Symbol(b, Decl(user.js, 3, 12))
20+
21+
const js0 = require("./js.js");
22+
>js0 : Symbol(js0, Decl(user.js, 7, 5))
23+
>require : Symbol(require)
24+
>"./js.js" : Symbol("/js", Decl(js.js, 0, 0))
25+
26+
json0.b; // Error (good)
27+
>json0 : Symbol(json0, Decl(user.js, 0, 5))
28+
29+
/** @type {{ b: number }} */
30+
const js1 = require("./js.js"); // Error (good)
31+
>js1 : Symbol(js1, Decl(user.js, 11, 5))
32+
>require : Symbol(require)
33+
>"./js.js" : Symbol("/js", Decl(js.js, 0, 0))
34+
35+
js1.b;
36+
>js1.b : Symbol(b, Decl(user.js, 10, 12))
37+
>js1 : Symbol(js1, Decl(user.js, 11, 5))
38+
>b : Symbol(b, Decl(user.js, 10, 12))
39+
40+
=== /json.json ===
41+
{ "a": 0 }
42+
>"a" : Symbol("a", Decl(json.json, 0, 1))
43+
44+
=== /js.js ===
45+
module.exports = { a: 0 };
46+
>module.exports : Symbol("/js", Decl(js.js, 0, 0))
47+
>module : Symbol(export=, Decl(js.js, 0, 0))
48+
>exports : Symbol(export=, Decl(js.js, 0, 0))
49+
>a : Symbol(a, Decl(js.js, 0, 18))
50+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== /user.js ===
2+
const json0 = require("./json.json");
3+
>json0 : { "a": number; }
4+
>require("./json.json") : { "a": number; }
5+
>require : any
6+
>"./json.json" : "./json.json"
7+
8+
json0.b; // Error (good)
9+
>json0.b : any
10+
>json0 : { "a": number; }
11+
>b : any
12+
13+
/** @type {{ b: number }} */
14+
const json1 = require("./json.json"); // No error (bad)
15+
>json1 : { b: number; }
16+
>require("./json.json") : { "a": number; }
17+
>require : any
18+
>"./json.json" : "./json.json"
19+
20+
json1.b; // No error (OK since that's the type annotation)
21+
>json1.b : number
22+
>json1 : { b: number; }
23+
>b : number
24+
25+
const js0 = require("./js.js");
26+
>js0 : { a: number; }
27+
>require("./js.js") : { a: number; }
28+
>require : any
29+
>"./js.js" : "./js.js"
30+
31+
json0.b; // Error (good)
32+
>json0.b : any
33+
>json0 : { "a": number; }
34+
>b : any
35+
36+
/** @type {{ b: number }} */
37+
const js1 = require("./js.js"); // Error (good)
38+
>js1 : { b: number; }
39+
>require("./js.js") : { a: number; }
40+
>require : any
41+
>"./js.js" : "./js.js"
42+
43+
js1.b;
44+
>js1.b : number
45+
>js1 : { b: number; }
46+
>b : number
47+
48+
=== /json.json ===
49+
{ "a": 0 }
50+
>{ "a": 0 } : { "a": number; }
51+
>"a" : number
52+
>0 : 0
53+
54+
=== /js.js ===
55+
module.exports = { a: 0 };
56+
>module.exports = { a: 0 } : { a: number; }
57+
>module.exports : { a: number; }
58+
>module : { "/js": { a: number; }; }
59+
>exports : { a: number; }
60+
>{ a: 0 } : { a: number; }
61+
>a : number
62+
>0 : 0
63+

tests/baselines/reference/requireOfJsonFileTypes.types

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import c = require('./c.json');
66
>c : (string | null)[]
77

88
import d = require('./d.json');
9-
>d : "dConfig"
9+
>d : string
1010

1111
import e = require('./e.json');
12-
>e : -10
12+
>e : number
1313

1414
import f = require('./f.json');
1515
>f : number[]
@@ -64,14 +64,14 @@ const stringOrNumberOrNull: string | number | null = c[0];
6464
>0 : 0
6565

6666
stringLiteral = d;
67-
>stringLiteral = d : "dConfig"
67+
>stringLiteral = d : string
6868
>stringLiteral : string
69-
>d : "dConfig"
69+
>d : string
7070

7171
numberLiteral = e;
72-
>numberLiteral = e : -10
72+
>numberLiteral = e : number
7373
>numberLiteral : number
74-
>e : -10
74+
>e : number
7575

7676
numberLiteral = f[0];
7777
>numberLiteral = f[0] : number
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @noEmit: true
4+
// @strict: true
5+
// @resolveJsonModule: true
6+
7+
// @Filename: /json.json
8+
{ "a": 0 }
9+
10+
// @Filename: /js.js
11+
module.exports = { a: 0 };
12+
13+
// @Filename: /user.js
14+
const json0 = require("./json.json");
15+
json0.b; // Error (good)
16+
17+
/** @type {{ b: number }} */
18+
const json1 = require("./json.json"); // No error (bad)
19+
json1.b; // No error (OK since that's the type annotation)
20+
21+
const js0 = require("./js.js");
22+
json0.b; // Error (good)
23+
24+
/** @type {{ b: number }} */
25+
const js1 = require("./js.js"); // Error (good)
26+
js1.b;

0 commit comments

Comments
 (0)