Skip to content

Commit e4610e3

Browse files
authored
Import types in JS with var x = require('./mod') (#22161)
1 parent 99d866d commit e4610e3

9 files changed

+370
-1
lines changed

src/compiler/checker.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -2049,6 +2049,18 @@ namespace ts {
20492049
if (initializer) {
20502050
namespace = getSymbolOfNode(initializer);
20512051
}
2052+
if (namespace.valueDeclaration &&
2053+
isVariableDeclaration(namespace.valueDeclaration) &&
2054+
isCommonJsRequire(namespace.valueDeclaration.initializer)) {
2055+
const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral;
2056+
const moduleSym = resolveExternalModuleName(moduleName, moduleName);
2057+
if (moduleSym) {
2058+
const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
2059+
if (resolvedModuleSymbol) {
2060+
namespace = resolvedModuleSymbol;
2061+
}
2062+
}
2063+
}
20522064
}
20532065
symbol = getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning);
20542066
if (!symbol) {
@@ -18133,7 +18145,7 @@ namespace ts {
1813318145

1813418146
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
1813518147
if (isInJavaScriptFile(node) && isCommonJsRequire(node)) {
18136-
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
18148+
return resolveExternalModuleTypeByLiteral(node.arguments[0] as StringLiteral);
1813718149
}
1813818150

1813918151
const returnType = getReturnTypeOfSignature(signature);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
tests/cases/conformance/salsa/use.js(1,10): error TS2304: Cannot find name 'require'.
2+
3+
4+
==== tests/cases/conformance/salsa/use.js (1 errors) ====
5+
var ex = require('./ex')
6+
~~~~~~~
7+
!!! error TS2304: Cannot find name 'require'.
8+
9+
// values work
10+
var crunch = new ex.Crunch(1);
11+
crunch.n
12+
13+
14+
// types work
15+
/**
16+
* @param {ex.Crunch} wrap
17+
*/
18+
function f(wrap) {
19+
wrap.n
20+
}
21+
22+
==== tests/cases/conformance/salsa/ex.js (0 errors) ====
23+
export class Crunch {
24+
/** @param {number} n */
25+
constructor(n) {
26+
this.n = n
27+
}
28+
m() {
29+
return this.n
30+
}
31+
}
32+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
=== tests/cases/conformance/salsa/use.js ===
2+
var ex = require('./ex')
3+
>ex : Symbol(ex, Decl(use.js, 0, 3))
4+
>'./ex' : Symbol("tests/cases/conformance/salsa/ex", Decl(ex.js, 0, 0))
5+
6+
// values work
7+
var crunch = new ex.Crunch(1);
8+
>crunch : Symbol(crunch, Decl(use.js, 3, 3))
9+
>ex.Crunch : Symbol(Crunch, Decl(ex.js, 0, 0))
10+
>ex : Symbol(ex, Decl(use.js, 0, 3))
11+
>Crunch : Symbol(Crunch, Decl(ex.js, 0, 0))
12+
13+
crunch.n
14+
>crunch.n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
15+
>crunch : Symbol(crunch, Decl(use.js, 3, 3))
16+
>n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
17+
18+
19+
// types work
20+
/**
21+
* @param {ex.Crunch} wrap
22+
*/
23+
function f(wrap) {
24+
>f : Symbol(f, Decl(use.js, 4, 8))
25+
>wrap : Symbol(wrap, Decl(use.js, 11, 11))
26+
27+
wrap.n
28+
>wrap.n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
29+
>wrap : Symbol(wrap, Decl(use.js, 11, 11))
30+
>n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
31+
}
32+
33+
=== tests/cases/conformance/salsa/ex.js ===
34+
export class Crunch {
35+
>Crunch : Symbol(Crunch, Decl(ex.js, 0, 0))
36+
37+
/** @param {number} n */
38+
constructor(n) {
39+
>n : Symbol(n, Decl(ex.js, 2, 16))
40+
41+
this.n = n
42+
>this.n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
43+
>this : Symbol(Crunch, Decl(ex.js, 0, 0))
44+
>n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
45+
>n : Symbol(n, Decl(ex.js, 2, 16))
46+
}
47+
m() {
48+
>m : Symbol(Crunch.m, Decl(ex.js, 4, 5))
49+
50+
return this.n
51+
>this.n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
52+
>this : Symbol(Crunch, Decl(ex.js, 0, 0))
53+
>n : Symbol(Crunch.n, Decl(ex.js, 2, 20))
54+
}
55+
}
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
=== tests/cases/conformance/salsa/use.js ===
2+
var ex = require('./ex')
3+
>ex : typeof "tests/cases/conformance/salsa/ex"
4+
>require('./ex') : typeof "tests/cases/conformance/salsa/ex"
5+
>require : any
6+
>'./ex' : "./ex"
7+
8+
// values work
9+
var crunch = new ex.Crunch(1);
10+
>crunch : Crunch
11+
>new ex.Crunch(1) : Crunch
12+
>ex.Crunch : typeof Crunch
13+
>ex : typeof "tests/cases/conformance/salsa/ex"
14+
>Crunch : typeof Crunch
15+
>1 : 1
16+
17+
crunch.n
18+
>crunch.n : number
19+
>crunch : Crunch
20+
>n : number
21+
22+
23+
// types work
24+
/**
25+
* @param {ex.Crunch} wrap
26+
*/
27+
function f(wrap) {
28+
>f : (wrap: Crunch) => void
29+
>wrap : Crunch
30+
31+
wrap.n
32+
>wrap.n : number
33+
>wrap : Crunch
34+
>n : number
35+
}
36+
37+
=== tests/cases/conformance/salsa/ex.js ===
38+
export class Crunch {
39+
>Crunch : Crunch
40+
41+
/** @param {number} n */
42+
constructor(n) {
43+
>n : number
44+
45+
this.n = n
46+
>this.n = n : number
47+
>this.n : number
48+
>this : this
49+
>n : number
50+
>n : number
51+
}
52+
m() {
53+
>m : () => number
54+
55+
return this.n
56+
>this.n : number
57+
>this : this
58+
>n : number
59+
}
60+
}
61+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
tests/cases/conformance/salsa/use.js(1,10): error TS2304: Cannot find name 'require'.
2+
3+
4+
==== tests/cases/conformance/salsa/use.js (1 errors) ====
5+
var ex = require('./ex')
6+
~~~~~~~
7+
!!! error TS2304: Cannot find name 'require'.
8+
9+
// values work
10+
var crunch = new ex.Crunch(1);
11+
crunch.n
12+
13+
14+
// types work
15+
/**
16+
* @param {ex.Greatest} greatest
17+
* @param {ex.Crunch} wrap
18+
*/
19+
function f(greatest, wrap) {
20+
greatest.day
21+
wrap.n
22+
}
23+
24+
==== tests/cases/conformance/salsa/ex.d.ts (0 errors) ====
25+
export type Greatest = { day: 1 }
26+
export class Crunch {
27+
n: number
28+
m(): number
29+
constructor(n: number)
30+
}
31+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
=== tests/cases/conformance/salsa/use.js ===
2+
var ex = require('./ex')
3+
>ex : Symbol(ex, Decl(use.js, 0, 3))
4+
>'./ex' : Symbol("tests/cases/conformance/salsa/ex", Decl(ex.d.ts, 0, 0))
5+
6+
// values work
7+
var crunch = new ex.Crunch(1);
8+
>crunch : Symbol(crunch, Decl(use.js, 3, 3))
9+
>ex.Crunch : Symbol(Crunch, Decl(ex.d.ts, 0, 33))
10+
>ex : Symbol(ex, Decl(use.js, 0, 3))
11+
>Crunch : Symbol(Crunch, Decl(ex.d.ts, 0, 33))
12+
13+
crunch.n
14+
>crunch.n : Symbol(Crunch.n, Decl(ex.d.ts, 1, 21))
15+
>crunch : Symbol(crunch, Decl(use.js, 3, 3))
16+
>n : Symbol(Crunch.n, Decl(ex.d.ts, 1, 21))
17+
18+
19+
// types work
20+
/**
21+
* @param {ex.Greatest} greatest
22+
* @param {ex.Crunch} wrap
23+
*/
24+
function f(greatest, wrap) {
25+
>f : Symbol(f, Decl(use.js, 4, 8))
26+
>greatest : Symbol(greatest, Decl(use.js, 12, 11))
27+
>wrap : Symbol(wrap, Decl(use.js, 12, 20))
28+
29+
greatest.day
30+
>greatest.day : Symbol(day, Decl(ex.d.ts, 0, 24))
31+
>greatest : Symbol(greatest, Decl(use.js, 12, 11))
32+
>day : Symbol(day, Decl(ex.d.ts, 0, 24))
33+
34+
wrap.n
35+
>wrap.n : Symbol(Crunch.n, Decl(ex.d.ts, 1, 21))
36+
>wrap : Symbol(wrap, Decl(use.js, 12, 20))
37+
>n : Symbol(Crunch.n, Decl(ex.d.ts, 1, 21))
38+
}
39+
40+
=== tests/cases/conformance/salsa/ex.d.ts ===
41+
export type Greatest = { day: 1 }
42+
>Greatest : Symbol(Greatest, Decl(ex.d.ts, 0, 0))
43+
>day : Symbol(day, Decl(ex.d.ts, 0, 24))
44+
45+
export class Crunch {
46+
>Crunch : Symbol(Crunch, Decl(ex.d.ts, 0, 33))
47+
48+
n: number
49+
>n : Symbol(Crunch.n, Decl(ex.d.ts, 1, 21))
50+
51+
m(): number
52+
>m : Symbol(Crunch.m, Decl(ex.d.ts, 2, 13))
53+
54+
constructor(n: number)
55+
>n : Symbol(n, Decl(ex.d.ts, 4, 16))
56+
}
57+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
=== tests/cases/conformance/salsa/use.js ===
2+
var ex = require('./ex')
3+
>ex : typeof "tests/cases/conformance/salsa/ex"
4+
>require('./ex') : typeof "tests/cases/conformance/salsa/ex"
5+
>require : any
6+
>'./ex' : "./ex"
7+
8+
// values work
9+
var crunch = new ex.Crunch(1);
10+
>crunch : Crunch
11+
>new ex.Crunch(1) : Crunch
12+
>ex.Crunch : typeof Crunch
13+
>ex : typeof "tests/cases/conformance/salsa/ex"
14+
>Crunch : typeof Crunch
15+
>1 : 1
16+
17+
crunch.n
18+
>crunch.n : number
19+
>crunch : Crunch
20+
>n : number
21+
22+
23+
// types work
24+
/**
25+
* @param {ex.Greatest} greatest
26+
* @param {ex.Crunch} wrap
27+
*/
28+
function f(greatest, wrap) {
29+
>f : (greatest: { day: 1; }, wrap: Crunch) => void
30+
>greatest : { day: 1; }
31+
>wrap : Crunch
32+
33+
greatest.day
34+
>greatest.day : 1
35+
>greatest : { day: 1; }
36+
>day : 1
37+
38+
wrap.n
39+
>wrap.n : number
40+
>wrap : Crunch
41+
>n : number
42+
}
43+
44+
=== tests/cases/conformance/salsa/ex.d.ts ===
45+
export type Greatest = { day: 1 }
46+
>Greatest : Greatest
47+
>day : 1
48+
49+
export class Crunch {
50+
>Crunch : Crunch
51+
52+
n: number
53+
>n : number
54+
55+
m(): number
56+
>m : () => number
57+
58+
constructor(n: number)
59+
>n : number
60+
}
61+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @strict: true
4+
// @noEmit: true
5+
// @Filename: ex.js
6+
export class Crunch {
7+
/** @param {number} n */
8+
constructor(n) {
9+
this.n = n
10+
}
11+
m() {
12+
return this.n
13+
}
14+
}
15+
16+
// @Filename: use.js
17+
var ex = require('./ex')
18+
19+
// values work
20+
var crunch = new ex.Crunch(1);
21+
crunch.n
22+
23+
24+
// types work
25+
/**
26+
* @param {ex.Crunch} wrap
27+
*/
28+
function f(wrap) {
29+
wrap.n
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @strict: true
4+
// @noEmit: true
5+
// @Filename: ex.d.ts
6+
export type Greatest = { day: 1 }
7+
export class Crunch {
8+
n: number
9+
m(): number
10+
constructor(n: number)
11+
}
12+
13+
// @Filename: use.js
14+
var ex = require('./ex')
15+
16+
// values work
17+
var crunch = new ex.Crunch(1);
18+
crunch.n
19+
20+
21+
// types work
22+
/**
23+
* @param {ex.Greatest} greatest
24+
* @param {ex.Crunch} wrap
25+
*/
26+
function f(greatest, wrap) {
27+
greatest.day
28+
wrap.n
29+
}

0 commit comments

Comments
 (0)