Skip to content

Commit 56b3725

Browse files
authored
feat(node-resolve): support .js imports in TypeScript (#480)
1 parent 7c6f519 commit 56b3725

File tree

8 files changed

+1161
-127
lines changed

8 files changed

+1161
-127
lines changed

package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"write-pkg": "^4.0.0"
2424
},
2525
"devDependencies": {
26-
"@typescript-eslint/eslint-plugin": "^2.14.0",
27-
"@typescript-eslint/parser": "^2.14.0",
26+
"@typescript-eslint/eslint-plugin": "^3.5.0",
27+
"@typescript-eslint/parser": "^3.5.0",
2828
"ava": "^2.4.0",
2929
"chalk": "^2.4.2",
3030
"codecov-lite": "^0.3.1",
@@ -38,7 +38,6 @@
3838
"pnpm": "^4.13.0",
3939
"prettier": "^1.19.1",
4040
"prettier-plugin-package": "^0.3.1",
41-
"rollup": "^2.0.0",
4241
"ts-node": "^8.5.4",
4342
"tsconfig-paths": "^3.9.0",
4443
"tslib": "^1.10.0",

packages/node-resolve/package.json

+9-8
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,23 @@
4848
"rollup": "^1.20.0||^2.0.0"
4949
},
5050
"dependencies": {
51-
"@rollup/pluginutils": "^3.0.8",
52-
"@types/resolve": "0.0.8",
51+
"@rollup/pluginutils": "^3.1.0",
52+
"@types/resolve": "1.17.1",
5353
"builtin-modules": "^3.1.0",
5454
"deep-freeze": "^0.0.1",
5555
"deepmerge": "^4.2.2",
5656
"is-module": "^1.0.0",
57-
"resolve": "^1.14.2"
57+
"resolve": "^1.17.0"
5858
},
5959
"devDependencies": {
60-
"@babel/core": "^7.9.0",
61-
"@babel/preset-env": "^7.9.0",
62-
"@rollup/plugin-json": "^4.0.1",
60+
"@babel/core": "^7.10.4",
61+
"@babel/plugin-transform-typescript": "^7.10.4",
62+
"@babel/preset-env": "^7.10.4",
63+
"@rollup/plugin-babel": "^5.0.4",
64+
"@rollup/plugin-commonjs": "^13.0.0",
65+
"@rollup/plugin-json": "^4.1.0",
6366
"es5-ext": "^0.10.53",
6467
"rollup": "^2.12.0",
65-
"rollup-plugin-babel": "^4.3.3",
66-
"rollup-plugin-commonjs": "^10.1.0",
6768
"source-map": "^0.7.3",
6869
"string-capitalize": "^1.0.1"
6970
},

packages/node-resolve/src/index.js

+9
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ export function nodeResolve(opts = {}) {
191191
importSpecifierList.push(`${importee}/`);
192192
}
193193

194+
// TypeScript files may import '.js' to refer to either '.ts' or '.tsx'
195+
if (importer && importee.endsWith('.js')) {
196+
for (const ext of ['.ts', '.tsx']) {
197+
if (importer.endsWith(ext) && extensions.includes(ext)) {
198+
importSpecifierList.push(importee.replace(/.js$/, ext));
199+
}
200+
}
201+
}
202+
194203
importSpecifierList.push(importee);
195204
resolveOptions = Object.assign(resolveOptions, customResolveOptions);
196205

packages/node-resolve/test/browser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const { join } = require('path');
22

33
const test = require('ava');
44
const { rollup } = require('rollup');
5-
const commonjs = require('rollup-plugin-commonjs');
5+
const commonjs = require('@rollup/plugin-commonjs');
66

77
const { testBundle } = require('../../../util/test');
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { main } from './main.js';
2+
// This resolves as main.ts and _not_ main.js, despite the extension
3+
const mainResult = main();
4+
export default mainResult;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// To make this very clearly TypeScript and not just JS with a TS extension
2+
type TestType = string | string[];
3+
interface Main {
4+
(): string;
5+
propertyCall(input?: TestType): TestType;
6+
}
7+
8+
const main: Main = () => 'It works!';
9+
main.propertyCall = () => '';
10+
11+
export { main };

packages/node-resolve/test/test.js

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
const { join, resolve } = require('path');
1+
import { join, resolve } from 'path';
22

3-
const test = require('ava');
4-
const { rollup } = require('rollup');
5-
const babel = require('rollup-plugin-babel');
6-
const commonjs = require('rollup-plugin-commonjs');
3+
import test from 'ava';
4+
import { rollup } from 'rollup';
5+
import babel from '@rollup/plugin-babel';
6+
import commonjs from '@rollup/plugin-commonjs';
77

8-
const { getCode, getImports, testBundle } = require('../../../util/test');
8+
import { getCode, getImports, testBundle } from '../../../util/test';
99

10-
const { nodeResolve } = require('..');
10+
import { nodeResolve } from '..';
1111

1212
process.chdir(join(__dirname, 'fixtures'));
1313

@@ -51,6 +51,7 @@ test('finds a file inside a package directory', async (t) => {
5151
plugins: [
5252
nodeResolve(),
5353
babel({
54+
babelHelpers: 'bundled',
5455
presets: [
5556
[
5657
'@babel/preset-env',
@@ -104,6 +105,25 @@ test('supports non-standard extensions', async (t) => {
104105
await testBundle(t, bundle);
105106
});
106107

108+
test('supports JS extensions in TS when referring to TS imports', async (t) => {
109+
const bundle = await rollup({
110+
input: 'ts-import-js-extension/import-ts-with-js-extension.ts',
111+
onwarn: () => t.fail('No warnings were expected'),
112+
plugins: [
113+
nodeResolve({
114+
extensions: ['.js', '.ts']
115+
}),
116+
babel({
117+
babelHelpers: 'bundled',
118+
plugins: ['@babel/plugin-transform-typescript'],
119+
extensions: ['.js', '.ts']
120+
})
121+
]
122+
});
123+
const { module } = await testBundle(t, bundle);
124+
t.is(module.exports, 'It works!');
125+
});
126+
107127
test('ignores IDs with null character', async (t) => {
108128
const result = await nodeResolve().resolveId('\0someid', 'test.js');
109129
t.is(result, null);

0 commit comments

Comments
 (0)