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

Always resolve package.json exports in type reference directives #58638

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
20 changes: 7 additions & 13 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -579,19 +579,13 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string

const failedLookupLocations: string[] = [];
const affectingLocations: string[] = [];
// Allow type reference directives to opt into `exports` resolution in any resolution mode
// when a `resolution-mode` override is present.
let features = getNodeResolutionFeatures(options);
if (resolutionMode !== undefined) {
features |= NodeResolutionFeatures.AllFeatures;
}

let features = NodeResolutionFeatures.AllFeatures;
const moduleResolution = getEmitModuleResolutionKind(options);
if (resolutionMode === ModuleKind.ESNext && (ModuleResolutionKind.Node16 <= moduleResolution && moduleResolution <= ModuleResolutionKind.NodeNext)) {
features |= NodeResolutionFeatures.EsmMode;
}
const conditions = (features & NodeResolutionFeatures.Exports)
? getConditions(options, resolutionMode)
: [];
const conditions = getConditions(options, resolutionMode);
const diagnostics: Diagnostic[] = [];
const moduleResolutionState: ModuleResolutionState = {
compilerOptions: options,
Expand Down Expand Up @@ -677,7 +671,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string
}
}
return resolvedTypeScriptOnly(
loadNodeModuleFromDirectory(Extensions.Declaration, candidate, !directoryExists, moduleResolutionState),
loadModuleFromSpecificNodeModulesDirectory(Extensions.Declaration, typeReferenceDirectiveName, typeRoot, directoryExists, moduleResolutionState, /*cache*/ undefined, redirectedReference, /*disableFileLookup*/ true),
);
});
}
Expand Down Expand Up @@ -3051,7 +3045,7 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod
}
}

function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): Resolved | undefined {
function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, disableFileLookup?: boolean): Resolved | undefined {
const candidate = normalizePath(combinePaths(nodeModulesDirectory, moduleName));
const { packageName, rest } = parsePackageName(moduleName);
const packageDirectory = combinePaths(nodeModulesDirectory, packageName);
Expand All @@ -3066,7 +3060,7 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu
!hasProperty((rootPackageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state))?.contents.packageJsonContent ?? emptyArray, "exports")
)
) {
const fromFile = loadModuleFromFile(extensions, candidate, !nodeModulesDirectoryExists, state);
const fromFile = !disableFileLookup && loadModuleFromFile(extensions, candidate, !nodeModulesDirectoryExists, state);
if (fromFile) {
return noPackageId(fromFile);
}
Expand All @@ -3083,7 +3077,7 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu
}

const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => {
let pathAndExtension = (rest || !(state.features & NodeResolutionFeatures.EsmMode)) && loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) ||
let pathAndExtension = (rest || !(state.features & NodeResolutionFeatures.EsmMode)) && !disableFileLookup && loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) ||
loadNodeModuleFromDirectoryWorker(
extensions,
candidate,
Expand Down
2 changes: 1 addition & 1 deletion src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2352,7 +2352,7 @@ export class TestState {
}

public baselineSyntacticAndSemanticDiagnostics() {
const files = ts.filter(this.getCompilerTestFiles(), f => !ts.endsWith(f.unitName, ".json"));
const files = ts.filter(this.getCompilerTestFiles(), f => !ts.endsWith(f.unitName, ".json") && (this.testType === FourSlashTestType.Server || !!this.languageService.getProgram()!.getSourceFile(f.unitName)));
const result = this.getSyntacticDiagnosticBaselineText(files)
+ Harness.IO.newLine()
+ Harness.IO.newLine()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
error TS2688: Cannot find type definition file for 'dedent4'.
The file is in the program because:
Entry point for implicit type library 'dedent4'
/index.cts(4,21): error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.
/index.mts(4,21): error TS2307: Cannot find module 'dedent4' or its corresponding type declarations.


!!! error TS2688: Cannot find type definition file for 'dedent4'.
!!! error TS2688: The file is in the program because:
!!! error TS2688: Entry point for implicit type library 'dedent4'
==== /node_modules/@types/dedent/package.json (0 errors) ====
{ "name": "@types/dedent", "version": "1.0.0", "main": "" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const a = <div></div>;
"main": "",
"types": "index.d.ts",
"exports": {
".": "./index.d.ts",
"./*.js": "./*.js",
"./*": "./*.js"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
"======== Resolving type reference directive 'react', containing file '/.src/__inferred type names__.ts', root directory '/.src/node_modules/@types,/node_modules/@types'. ========",
"Resolving with primary search path '/.src/node_modules/@types, /node_modules/@types'.",
"File '/.src/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'index.d.ts' that references '/.src/node_modules/@types/react/index.d.ts'.",
"Using 'exports' subpath '.' with target './index.d.ts'.",
"File '/.src/node_modules/@types/react/index.d.ts' exists - use it as a name resolution result.",
"Resolving real path for '/.src/node_modules/@types/react/index.d.ts', result '/.src/node_modules/@types/react/index.d.ts'.",
"======== Type reference directive 'react' was successfully resolved to '/.src/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1', primary: true. ========",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error TS2688: Cannot find type definition file for 'foo'.
The file is in the program because:
Entry point for implicit type library 'foo'
/app.ts(1,30): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?
/app.ts(2,29): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?
/app.ts(3,30): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?


!!! error TS2688: Cannot find type definition file for 'foo'.
!!! error TS2688: The file is in the program because:
!!! error TS2688: Entry point for implicit type library 'foo'
==== /node_modules/@types/foo/package.json (0 errors) ====
{
"name": "@types/foo",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error TS2688: Cannot find type definition file for 'foo'.
The file is in the program because:
Entry point for implicit type library 'foo'
/app.ts(1,35): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?
/app.ts(2,34): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?
/app.ts(3,35): error TS2792: Cannot find module 'foo'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?


!!! error TS2688: Cannot find type definition file for 'foo'.
!!! error TS2688: The file is in the program because:
!!! error TS2688: Entry point for implicit type library 'foo'
==== /node_modules/@types/foo/package.json (0 errors) ====
{
"name": "@types/foo",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
error TS2688: Cannot find type definition file for 'bar'.
The file is in the program because:
Entry point for implicit type library 'bar'
error TS6504: File '/node_modules/bar/index.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
Expand All @@ -16,6 +19,9 @@ error TS6504: File '/node_modules/foo/index.mjs' is a JavaScript file. Did you m
There are types at '/node_modules/@types/bar/index.d.ts', but this result could not be resolved when respecting package.json "exports". The '@types/bar' library may need to update its package.json or typings.


!!! error TS2688: Cannot find type definition file for 'bar'.
!!! error TS2688: The file is in the program because:
!!! error TS2688: Entry point for implicit type library 'bar'
!!! error TS6504: File '/node_modules/bar/index.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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,26 @@
"Resolving with primary search path '/.src/node_modules/@types, /node_modules/@types'.",
"Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.",
"File '/node_modules/@types/bar/package.json' exists according to earlier cached lookups.",
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'index.d.ts' that references '/node_modules/@types/bar/index.d.ts'.",
"File '/node_modules/@types/bar/index.d.ts' exists - use it as a name resolution result.",
"Resolving real path for '/node_modules/@types/bar/index.d.ts', result '/node_modules/@types/bar/index.d.ts'.",
"======== Type reference directive 'bar' was successfully resolved to '/node_modules/@types/bar/index.d.ts' with Package ID '@types/bar/index.d.ts@1.0.0', primary: true. ========",
"Entering conditional exports.",
"Saw non-matching condition 'require'.",
"Exiting conditional exports.",
"Looking up in 'node_modules' folder, initial location '/.src'.",
"Searching all ancestor node_modules directories for preferred extensions: Declaration.",
"Directory '/.src/node_modules' does not exist, skipping all lookups in it.",
"File '/node_modules/bar/package.json' exists according to earlier cached lookups.",
"Entering conditional exports.",
"Matched 'exports' condition 'import'.",
"Using 'exports' subpath '.' with target './index.mjs'.",
"File name '/node_modules/bar/index.mjs' has a '.mjs' extension - stripping it.",
"File '/node_modules/bar/index.d.mts' does not exist.",
"Failed to resolve under condition 'import'.",
"Saw non-matching condition 'require'.",
"Exiting conditional exports.",
"File '/node_modules/@types/bar/package.json' exists according to earlier cached lookups.",
"Entering conditional exports.",
"Saw non-matching condition 'require'.",
"Exiting conditional exports.",
"======== Type reference directive 'bar' was not resolved. ========",
"File '/.ts/package.json' does not exist.",
"File '/package.json' does not exist according to earlier cached lookups.",
"======== Resolving module '@typescript/lib-es5' from '/.src/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,12 @@
"Resolving with primary search path '/.src/node_modules/@types, /node_modules/@types'.",
"Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.",
"File '/node_modules/@types/bar/package.json' exists according to earlier cached lookups.",
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'index.d.ts' that references '/node_modules/@types/bar/index.d.ts'.",
"Entering conditional exports.",
"Matched 'exports' condition 'require'.",
"Using 'exports' subpath '.' with target './index.d.ts'.",
"File '/node_modules/@types/bar/index.d.ts' exists - use it as a name resolution result.",
"Resolved under condition 'require'.",
"Exiting conditional exports.",
"Resolving real path for '/node_modules/@types/bar/index.d.ts', result '/node_modules/@types/bar/index.d.ts'.",
"======== Type reference directive 'bar' was successfully resolved to '/node_modules/@types/bar/index.d.ts' with Package ID '@types/bar/index.d.ts@1.0.0', primary: true. ========",
"File '/.ts/package.json' does not exist.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
usage.ts(1,23): error TS2688: Cannot find type definition file for 'pkg'.


==== node_modules/pkg/index.d.ts (0 errors) ====
interface GlobalThing { a: number }
==== node_modules/pkg/package.json (0 errors) ====
{
"name": "pkg",
"types": "index.d.ts",
"exports": "some-other-thing.js"
}
==== usage.ts (1 errors) ====
/// <reference types="pkg" />
~~~
!!! error TS2688: Cannot find type definition file for 'pkg'.

const a: GlobalThing = { a: 0 };
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,17 @@ File '/Users/name/projects/web/node_modules/@types/yargs/package.json' exists ac
======== Resolving type reference directive 'yargs', containing file '/Users/name/projects/web/__inferred type names__.ts', root directory '/Users/name/projects/web/node_modules/@types,/Users/name/projects/node_modules/@types,/Users/name/node_modules/@types,/Users/node_modules/@types,/node_modules/@types'. ========
Resolving with primary search path '/Users/name/projects/web/node_modules/@types, /Users/name/projects/node_modules/@types, /Users/name/node_modules/@types, /Users/node_modules/@types, /node_modules/@types'.
File '/Users/name/projects/web/node_modules/@types/yargs/package.json' exists according to earlier cached lookups.
'package.json' does not have a 'typesVersions' field.
'package.json' does not have a 'typings' field.
'package.json' does not have a 'types' field.
'package.json' does not have a 'main' field.
Entering conditional exports.
Matched 'exports' condition 'types'.
Entering conditional exports.
Saw non-matching condition 'import'.
Matched 'exports' condition 'default'.
Using 'exports' subpath '.' with target './index.d.ts'.
File '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' exists - use it as a name resolution result.
Resolved under condition 'default'.
Exiting conditional exports.
Resolved under condition 'types'.
Exiting conditional exports.
Resolving real path for '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts', result '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts'.
======== Type reference directive 'yargs' was successfully resolved to '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' with Package ID 'yargs/index.d.ts@17.0.12', primary: true. ========
File '/a/lib/package.json' does not exist.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,15 @@ Info seq [hh:mm:ss:mss] event:
}
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /node_modules/@types/dependency/package.json 2000 undefined Project: /dev/null/inferredProject1* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /node_modules/@types/dependency/lib/package.json 2000 undefined Project: /dev/null/inferredProject1* WatchType: File location affecting resolution
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] Files (5)
/lib.d.ts Text-1 lib.d.ts-Text
/lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text
/lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text
/tsconfig.json SVC-1-0 "{\n \"compilerOptions\": {\n \"module\": \"nodenext\"\n }\n}"
/node_modules/@types/dependency/lib/index.d.ts Text-1 "export declare function fooFromIndex(): void;"


lib.d.ts
Expand All @@ -171,6 +173,9 @@ Info seq [hh:mm:ss:mss] Files (4)
Library referenced via 'decorators.legacy' from file 'lib.d.ts'
tsconfig.json
Root file specified for compilation
node_modules/@types/dependency/lib/index.d.ts
Entry point for implicit type library 'dependency' with packageId '@types/dependency/lib/index.d.ts@1.0.0'
File is ECMAScript module because 'node_modules/@types/dependency/package.json' has field "type" with value "module"

Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /package.json 250 undefined WatchType: package.json file
Expand All @@ -179,7 +184,7 @@ Info seq [hh:mm:ss:mss] Files (5)

Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] Files (5)

Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Expand All @@ -197,6 +202,7 @@ watchedFiles::
{"pollingInterval":500}
/node_modules/@types/dependency/lib/package.json: *new*
{"pollingInterval":2000}
{"pollingInterval":2000}
/node_modules/@types/dependency/package.json: *new*
{"pollingInterval":2000}
{"pollingInterval":2000}
Expand Down Expand Up @@ -238,8 +244,9 @@ ScriptInfos::
/dev/null/inferredProject1*
/node_modules/@types/dependency/lib/index.d.ts *new*
version: Text-1
containingProjects: 1
containingProjects: 2
/tsconfig.json
/dev/null/inferredProject1*
/src/foo.ts *new*
version: Text-1
containingProjects: 1
Expand All @@ -265,7 +272,7 @@ Info seq [hh:mm:ss:mss] Files (5)

Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] Files (5)

Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Expand All @@ -285,6 +292,7 @@ watchedFiles::
{"pollingInterval":500}
/node_modules/@types/dependency/lib/package.json:
{"pollingInterval":2000}
{"pollingInterval":2000}
/node_modules/@types/dependency/package.json:
{"pollingInterval":2000}
{"pollingInterval":2000}
Expand Down Expand Up @@ -328,8 +336,9 @@ ScriptInfos::
/dev/null/inferredProject1*
/node_modules/@types/dependency/lib/index.d.ts
version: Text-1
containingProjects: 1
containingProjects: 2
/tsconfig.json
/dev/null/inferredProject1*
/src/foo.ts (Open) *changed*
open: true *changed*
version: Text-1
Expand Down Expand Up @@ -1140,6 +1149,7 @@ watchedFiles::
/node_modules/@types/dependency/lib/lol.d.ts: *new*
{"pollingInterval":500}
/node_modules/@types/dependency/lib/package.json:
{"pollingInterval":2000}
{"pollingInterval":2000}
{"pollingInterval":2000} *new*
/node_modules/@types/dependency/package.json:
Expand Down Expand Up @@ -1187,8 +1197,9 @@ ScriptInfos::
/dev/null/inferredProject1*
/node_modules/@types/dependency/lib/index.d.ts
version: Text-1
containingProjects: 1
containingProjects: 2
/tsconfig.json
/dev/null/inferredProject1*
/node_modules/@types/dependency/lib/lol.d.ts *new*
version: Text-1
containingProjects: 1
Expand Down
Loading
Loading