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

package.json exports should have priority over typesVersions #50890

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 17 additions & 18 deletions src/compiler/moduleNameResolver.ts
Expand Up @@ -2437,12 +2437,7 @@ namespace ts {
}
}

const { packageName, rest } = parsePackageName(moduleName);
const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => {
// package exports are higher priority than file/directory lookups (and, if there's exports present, blocks them)
if (packageInfo && packageInfo.contents.packageJsonContent.exports && state.features & NodeResolutionFeatures.Exports) {
return loadModuleFromExports(packageInfo, extensions, combinePaths(".", rest), state, cache, redirectedReference)?.value;
}
let pathAndExtension =
loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) ||
loadNodeModuleFromDirectoryWorker(
Expand All @@ -2466,20 +2461,24 @@ namespace ts {
return withPackageId(packageInfo, pathAndExtension);
};

if (rest !== "") { // If "rest" is empty, we just did this search above.
const packageDirectory = combinePaths(nodeModulesDirectory, packageName);

// Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings.
const { packageName, rest } = parsePackageName(moduleName);
const packageDirectory = combinePaths(nodeModulesDirectory, packageName);
if (rest !== "") {
// Previous `packageInfo` may have been from a nested package.json; ensure we have the one from the package root now.
packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state);
if (packageInfo && packageInfo.contents.versionPaths) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, packageInfo.contents.versionPaths.version, version, rest);
}
const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host);
const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, packageInfo.contents.versionPaths.paths, /*pathPatterns*/ undefined, loader, !packageDirectoryExists, state);
if (fromPaths) {
return fromPaths.value;
}
}
// package exports are higher priority than file/directory/typesVersions lookups and (and, if there's exports present, blocks them)
if (packageInfo && packageInfo.contents.packageJsonContent.exports && state.features & NodeResolutionFeatures.Exports) {
return loadModuleFromExports(packageInfo, extensions, combinePaths(".", rest), state, cache, redirectedReference)?.value;
}
if (rest !== "" && packageInfo && packageInfo.contents.versionPaths) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, packageInfo.contents.versionPaths.version, version, rest);
}
const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host);
const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, packageInfo.contents.versionPaths.paths, /*pathPatterns*/ undefined, loader, !packageDirectoryExists, state);
if (fromPaths) {
return fromPaths.value;
}
}

Expand Down
@@ -0,0 +1,92 @@
error TS6504: File '/node_modules/exports-and-types-versions/dist/foo.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
The file is in the program because:
Root file specified for compilation
/main.cts(1,16): error TS7016: Could not find a declaration file for module 'exports-and-types-versions/foo'. '/node_modules/exports-and-types-versions/dist/foo.js' implicitly has an 'any' type.
If the 'exports-and-types-versions' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'exports-and-types-versions/foo';`
/main.cts(2,16): error TS2307: Cannot find module 'exports-and-types-versions/nope' or its corresponding type declarations.
/main.cts(5,16): error TS2307: Cannot find module 'exports-and-types-versions/versioned-nah' or its corresponding type declarations.
/main.mts(1,16): error TS7016: Could not find a declaration file for module 'exports-and-types-versions/foo'. '/node_modules/exports-and-types-versions/dist/foo.js' implicitly has an 'any' type.
If the 'exports-and-types-versions' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'exports-and-types-versions/foo';`
/main.mts(2,16): error TS2307: Cannot find module 'exports-and-types-versions/nope' or its corresponding type declarations.
/main.mts(5,16): error TS2307: Cannot find module 'exports-and-types-versions/versioned-nah' or its corresponding type declarations.


!!! error TS6504: File '/node_modules/exports-and-types-versions/dist/foo.js' is a JavaScript file. Did you mean to enable the 'allowJs' option?
!!! error TS6504: The file is in the program because:
!!! error TS6504: Root file specified for compilation
==== /node_modules/exports-and-types-versions/package.json (0 errors) ====
{
"name": "exports-and-types-versions",
"version": "1.0.0",
"exports": {
"./foo": "./dist/foo.js",
"./yep": {
"types": "./types/foo.d.ts",
"default": "./dist/foo.js"
},
"./versioned-yep": {
"types@>=4": "./types/foo.d.ts"
},
"./versioned-nah": {
"types@<4": "./types/foo.d.ts"
}
},
"typesVersions": {
"*": {
"foo": ["./types/foo.d.ts"],
"nope": ["./types/foo.d.ts"],
"versioned-nah": ["./types/foo.d.ts"]
}
}
}

==== /node_modules/exports-and-types-versions/dist/foo.js (0 errors) ====
module.exports = {};

==== /node_modules/exports-and-types-versions/types/foo.d.ts (0 errors) ====
export {};

==== /node_modules/just-types-versions/package.json (0 errors) ====
{
"name": "just-types-versions",
"version": "1.0.0",
"typesVersions": {
"*": {
"foo": ["./types/foo.d.ts"]
}
}
}

==== /node_modules/just-types-versions/types/foo.d.ts (0 errors) ====
export {};

==== /main.cts (3 errors) ====
import {} from "exports-and-types-versions/foo";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7016: Could not find a declaration file for module 'exports-and-types-versions/foo'. '/node_modules/exports-and-types-versions/dist/foo.js' implicitly has an 'any' type.
!!! error TS7016: If the 'exports-and-types-versions' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'exports-and-types-versions/foo';`
import {} from "exports-and-types-versions/nope";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'exports-and-types-versions/nope' or its corresponding type declarations.
import {} from "exports-and-types-versions/yep";
import {} from "exports-and-types-versions/versioned-yep";
import {} from "exports-and-types-versions/versioned-nah";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'exports-and-types-versions/versioned-nah' or its corresponding type declarations.
import {} from "just-types-versions/foo";

==== /main.mts (3 errors) ====
import {} from "exports-and-types-versions/foo";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7016: Could not find a declaration file for module 'exports-and-types-versions/foo'. '/node_modules/exports-and-types-versions/dist/foo.js' implicitly has an 'any' type.
!!! error TS7016: If the 'exports-and-types-versions' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module 'exports-and-types-versions/foo';`
import {} from "exports-and-types-versions/nope";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'exports-and-types-versions/nope' or its corresponding type declarations.
import {} from "exports-and-types-versions/yep";
import {} from "exports-and-types-versions/versioned-yep";
import {} from "exports-and-types-versions/versioned-nah";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'exports-and-types-versions/versioned-nah' or its corresponding type declarations.
import {} from "just-types-versions/foo";

@@ -0,0 +1,70 @@
//// [tests/cases/conformance/node/nodeModulesExportsBlocksTypesVersions.ts] ////

//// [package.json]
{
"name": "exports-and-types-versions",
"version": "1.0.0",
"exports": {
"./foo": "./dist/foo.js",
"./yep": {
"types": "./types/foo.d.ts",
"default": "./dist/foo.js"
},
"./versioned-yep": {
"types@>=4": "./types/foo.d.ts"
},
"./versioned-nah": {
"types@<4": "./types/foo.d.ts"
}
},
"typesVersions": {
"*": {
"foo": ["./types/foo.d.ts"],
"nope": ["./types/foo.d.ts"],
"versioned-nah": ["./types/foo.d.ts"]
}
}
}

//// [foo.js]
module.exports = {};

//// [foo.d.ts]
export {};

//// [package.json]
{
"name": "just-types-versions",
"version": "1.0.0",
"typesVersions": {
"*": {
"foo": ["./types/foo.d.ts"]
}
}
}

//// [foo.d.ts]
export {};

//// [main.cts]
import {} from "exports-and-types-versions/foo";
import {} from "exports-and-types-versions/nope";
import {} from "exports-and-types-versions/yep";
import {} from "exports-and-types-versions/versioned-yep";
import {} from "exports-and-types-versions/versioned-nah";
import {} from "just-types-versions/foo";

//// [main.mts]
import {} from "exports-and-types-versions/foo";
import {} from "exports-and-types-versions/nope";
import {} from "exports-and-types-versions/yep";
import {} from "exports-and-types-versions/versioned-yep";
import {} from "exports-and-types-versions/versioned-nah";
import {} from "just-types-versions/foo";


//// [main.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//// [main.mjs]
export {};
@@ -0,0 +1,23 @@
=== /node_modules/exports-and-types-versions/types/foo.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /node_modules/just-types-versions/types/foo.d.ts ===
export {};
No type information for this code.
No type information for this code.=== /main.cts ===
import {} from "exports-and-types-versions/foo";
No type information for this code.import {} from "exports-and-types-versions/nope";
No type information for this code.import {} from "exports-and-types-versions/yep";
No type information for this code.import {} from "exports-and-types-versions/versioned-yep";
No type information for this code.import {} from "exports-and-types-versions/versioned-nah";
No type information for this code.import {} from "just-types-versions/foo";
No type information for this code.
No type information for this code.=== /main.mts ===
import {} from "exports-and-types-versions/foo";
No type information for this code.import {} from "exports-and-types-versions/nope";
No type information for this code.import {} from "exports-and-types-versions/yep";
No type information for this code.import {} from "exports-and-types-versions/versioned-yep";
No type information for this code.import {} from "exports-and-types-versions/versioned-nah";
No type information for this code.import {} from "just-types-versions/foo";
No type information for this code.
No type information for this code.