Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -8519,5 +8519,9 @@
"'{0}' is not a valid meta-property for keyword 'import'. Did you mean 'meta' or 'defer'?": {
"category": "Error",
"code": 18061
},
"This import could not be resolved using the '{0}' exports condition in its package.json. Types were found using the condition '{1}', but this lower-priority condition will not be used at runtime. This is a bug in the '{2}' library's typings configuration.": {
"category": "Error",
"code": 18062
}
}
41 changes: 20 additions & 21 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
forEachAncestorDirectory,
formatMessage,
getAllowImportingTsExtensions,
getAllowJSCompilerOption,
getAnyExtensionFromPath,
getBaseFileName,
GetCanonicalFileName,
Expand Down Expand Up @@ -327,6 +326,8 @@ export interface ModuleResolutionState {
isConfigLookup: boolean;
candidateIsFromPackageJsonField: boolean;
resolvedPackageDirectory: boolean;
/** When beginning a fallback lookup in exports conditions, value is set to the object containing the conditions */
inFallbackConditionsLookup?: object;
}

/** Just the fields that we use for module resolution.
Expand Down Expand Up @@ -2586,26 +2587,7 @@ function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: str
}
const trailingParts = parts.slice(nameParts.length);
const subpath = !length(trailingParts) ? "." : `.${directorySeparator}${trailingParts.join(directorySeparator)}`;
// Maybe TODO: splitting extensions into two priorities should be unnecessary, except
// https://github.com/microsoft/TypeScript/issues/50762 makes the behavior different.
// As long as that bug exists, we need to do two passes here in self-name loading
// in order to be consistent with (non-self) library-name loading in
// `loadModuleFromNearestNodeModulesDirectoryWorker`, which uses two passes in order
// to prioritize `@types` packages higher up the directory tree over untyped
// implementation packages. See the selfNameModuleAugmentation.ts test for why this
// matters.
//
// However, there's an exception. If the user has `allowJs` and `declaration`, we need
// to ensure that self-name imports of their own package can resolve back to their
// input JS files via `tryLoadInputFileForPath` at a higher priority than their output
// declaration files, so we need to do a single pass with all extensions for that case.
if (getAllowJSCompilerOption(state.compilerOptions) && !pathContainsNodeModules(directory)) {
return loadModuleFromExports(scope, extensions, subpath, state, cache, redirectedReference);
}
const priorityExtensions = extensions & (Extensions.TypeScript | Extensions.Declaration);
const secondaryExtensions = extensions & ~(Extensions.TypeScript | Extensions.Declaration);
return loadModuleFromExports(scope, priorityExtensions, subpath, state, cache, redirectedReference)
|| loadModuleFromExports(scope, secondaryExtensions, subpath, state, cache, redirectedReference);
return loadModuleFromExports(scope, extensions, subpath, state, cache, redirectedReference);
}

function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, subpath: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult<Resolved> {
Expand Down Expand Up @@ -2806,6 +2788,7 @@ function getLoadModuleFromTargetExportOrImport(extensions: Extensions, state: Mo
else if (typeof target === "object" && target !== null) { // eslint-disable-line no-restricted-syntax
if (!Array.isArray(target)) {
traceIfEnabled(state, Diagnostics.Entering_conditional_exports);
const saveInFallbackConditionsLookup = state.inFallbackConditionsLookup;
for (const condition of getOwnKeys(target as MapLike<unknown>)) {
if (condition === "default" || state.conditions.includes(condition) || isApplicableVersionedTypesKey(state.conditions, condition)) {
traceIfEnabled(state, Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition);
Expand All @@ -2814,17 +2797,33 @@ function getLoadModuleFromTargetExportOrImport(extensions: Extensions, state: Mo
if (result) {
traceIfEnabled(state, Diagnostics.Resolved_under_condition_0, condition);
traceIfEnabled(state, Diagnostics.Exiting_conditional_exports);
if (state.inFallbackConditionsLookup === target) {
const firstMatchingCondition = getOwnKeys(target as MapLike<unknown>).find(c => c === "default" || state.conditions.includes(c) || isApplicableVersionedTypesKey(state.conditions, c))!;
const packageName = scope.contents.packageJsonContent.name || scope.packageDirectory;
state.reportDiagnostic(createCompilerDiagnostic(
Diagnostics.This_import_could_not_be_resolved_using_the_0_exports_condition_in_its_package_json_Types_were_found_using_the_condition_1_but_this_lower_priority_condition_will_not_be_used_at_runtime_This_is_a_bug_in_the_2_library_s_typings_configuration,
firstMatchingCondition,
condition,
packageName,
));
}
return result;
}
else {
traceIfEnabled(state, Diagnostics.Failed_to_resolve_under_condition_0, condition);
if (isImports) {
// Don't use fallback conditions for imports, since the user can fix their own package.json
return { value: undefined };
}
state.inFallbackConditionsLookup = target;
}
}
else {
traceIfEnabled(state, Diagnostics.Saw_non_matching_condition_0, condition);
}
}
traceIfEnabled(state, Diagnostics.Exiting_conditional_exports);
state.inFallbackConditionsLookup = saveInFallbackConditionsLookup;
return undefined;
}
else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.


!!! error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.
==== /node_modules/dep/package.json (0 errors) ====
{
"name": "dep",
"version": "1.0.0",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
}
}
}

==== /node_modules/dep/dist/index.d.ts (0 errors) ====
export {};

==== /node_modules/dep/dist/index.mjs (0 errors) ====
export {};

==== /index.mts (0 errors) ====
import {} from "dep";
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolution' is set to 'Node16'.
error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.


!!! error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolution' is set to 'Node16'.
!!! error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.
==== /node_modules/dep/package.json (0 errors) ====
{
"name": "dep",
Expand All @@ -22,9 +24,4 @@ error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolut
export {};

==== /index.mts (0 errors) ====
import {} from "dep";
// Should be an untyped resolution to dep/dist/index.mjs,
// but the first search is only for TS files, and when
// there's no dist/index.d.mts, it continues looking for
// matching conditions and resolves via `types`.

import {} from "dep";
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.
error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.


!!! error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.
!!! error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'types', but this lower-priority condition will not be used at runtime. This is a bug in the 'dep' library's typings configuration.
==== /node_modules/dep/package.json (0 errors) ====
{
"name": "dep",
Expand All @@ -22,9 +24,4 @@ error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResol
export {};

==== /index.mts (0 errors) ====
import {} from "dep";
// Should be an untyped resolution to dep/dist/index.mjs,
// but the first search is only for TS files, and when
// there's no dist/index.d.mts, it continues looking for
// matching conditions and resolves via `types`.

import {} from "dep";
38 changes: 38 additions & 0 deletions tests/baselines/reference/selfNameModuleAugmentation.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'default', but this lower-priority condition will not be used at runtime. This is a bug in the 'acorn-walk' library's typings configuration.
/index.ts(1,10): error TS2305: Module '"acorn-walk"' has no exported member 'simple'.


!!! error TS18062: This import could not be resolved using the 'import' exports condition in its package.json. Types were found using the condition 'default', but this lower-priority condition will not be used at runtime. This is a bug in the 'acorn-walk' library's typings configuration.
==== /node_modules/acorn-walk/package.json (0 errors) ====
{
"name": "acorn-walk",
"version": "8.2.0",
"main": "dist/walk.js",
"types": "dist/walk.d.ts",
"exports": {
".": [
{
"import": "./dist/walk.mjs",
"require": "./dist/walk.js",
"default": "./dist/walk.js"
},
"./dist/walk.js"
],
"./package.json": "./package.json"
}
}

==== /node_modules/acorn-walk/dist/walk.d.ts (0 errors) ====
export {};
declare module 'acorn-walk' {
export function simple(node: any, visitors: any, base?: any, state?: any): any;
}

==== /node_modules/acorn-walk/dist/walk.mjs (0 errors) ====
export {};

==== /index.ts (1 errors) ====
import { simple } from 'acorn-walk';
~~~~~~
!!! error TS2305: Module '"acorn-walk"' has no exported member 'simple'.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
=== /node_modules/acorn-walk/dist/walk.d.ts ===
export {};
declare module 'acorn-walk' {
>'acorn-walk' : Symbol("/node_modules/acorn-walk/dist/walk", Decl(walk.d.ts, 0, 0), Decl(walk.d.ts, 0, 10))
>'acorn-walk' : Symbol("/node_modules/acorn-walk/dist/walk", Decl(walk.mjs, 0, 0), Decl(walk.d.ts, 0, 10))

export function simple(node: any, visitors: any, base?: any, state?: any): any;
>simple : Symbol(simple, Decl(walk.d.ts, 1, 29))
Expand Down
13 changes: 3 additions & 10 deletions tests/baselines/reference/selfNameModuleAugmentation.trace.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,11 @@
"File name '/node_modules/acorn-walk/dist/walk.mjs' has a '.mjs' extension - stripping it.",
"File '/node_modules/acorn-walk/dist/walk.mts' does not exist.",
"File '/node_modules/acorn-walk/dist/walk.d.mts' does not exist.",
"Failed to resolve under condition 'import'.",
"Saw non-matching condition 'require'.",
"Matched 'exports' condition 'default'.",
"Using 'exports' subpath '.' with target './dist/walk.js'.",
"File name '/node_modules/acorn-walk/dist/walk.js' has a '.js' extension - stripping it.",
"File '/node_modules/acorn-walk/dist/walk.ts' does not exist.",
"File '/node_modules/acorn-walk/dist/walk.tsx' does not exist.",
"File '/node_modules/acorn-walk/dist/walk.d.ts' exists - use it as a name resolution result.",
"File '/node_modules/acorn-walk/dist/walk.mjs' exists - use it as a name resolution result.",
"'package.json' does not have a 'peerDependencies' field.",
"Resolved under condition 'default'.",
"Resolved under condition 'import'.",
"Exiting conditional exports.",
"======== Module name 'acorn-walk' was successfully resolved to '/node_modules/acorn-walk/dist/walk.d.ts' with Package ID 'acorn-walk/dist/walk.d.ts@8.2.0'. ========",
"======== Module name 'acorn-walk' was successfully resolved to '/node_modules/acorn-walk/dist/walk.mjs' with Package ID 'acorn-walk/dist/walk.mjs@8.2.0'. ========",
"======== Resolving module 'acorn-walk' from '/index.ts'. ========",
"Explicitly specified module resolution kind: 'Bundler'.",
"Resolving in CJS mode with conditions 'import', 'types'.",
Expand Down
8 changes: 6 additions & 2 deletions tests/baselines/reference/selfNameModuleAugmentation.types
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ declare module 'acorn-walk' {
>simple : (node: any, visitors: any, base?: any, state?: any) => any
> : ^ ^^ ^^ ^^ ^^ ^^^ ^^ ^^^ ^^^^^
>node : any
> : ^^^
>visitors : any
> : ^^^
>base : any
> : ^^^
>state : any
> : ^^^
}

=== /node_modules/acorn-walk/dist/walk.mjs ===
Expand All @@ -21,6 +25,6 @@ export {};

=== /index.ts ===
import { simple } from 'acorn-walk';
>simple : (node: any, visitors: any, base?: any, state?: any) => any
> : ^ ^^ ^^ ^^ ^^ ^^^ ^^ ^^^ ^^^^^
>simple : any
> : ^^^

Original file line number Diff line number Diff line change
Expand Up @@ -1118,10 +1118,6 @@ Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/workspa
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/project/src 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/project/dist 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/project/dist 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/project/node_modules 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/project/node_modules 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/node_modules 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/workspaces/node_modules 1 undefined Project: /home/src/workspaces/project/tsconfig.json WatchType: Failed Lookup Locations
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /home/src/workspaces/project/tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: SafeModules Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/home/src/workspaces/project/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (2)
Expand Down Expand Up @@ -1183,7 +1179,6 @@ watchedFiles::
watchedDirectoriesRecursive::
/home/src/workspaces/node_modules:
{}
{} *new*
/home/src/workspaces/node_modules/@types:
{}
{}
Expand All @@ -1193,7 +1188,6 @@ watchedDirectoriesRecursive::
{}
/home/src/workspaces/project/node_modules:
{}
{} *new*
/home/src/workspaces/project/node_modules/@types:
{}
{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,4 @@ export {};
export {};

// @Filename: /index.mts
import {} from "dep";
// Should be an untyped resolution to dep/dist/index.mjs,
// but the first search is only for TS files, and when
// there's no dist/index.d.mts, it continues looking for
// matching conditions and resolves via `types`.
import {} from "dep";
Loading