From f9f9a53c264686609d384986eb554a1bce17ab1b Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:45:55 -0800 Subject: [PATCH 1/2] test --- ...cTypeDirectiveResolutionBundler.errors.txt | 49 ++++++++++++++++++ ...aticTypeDirectiveResolutionBundler.symbols | 45 +++++++++++++++++ ...cTypeDirectiveResolutionBundler.trace.json | 43 ++++++++++++++++ ...omaticTypeDirectiveResolutionBundler.types | 44 ++++++++++++++++ ...automaticTypeDirectiveResolutionBundler.ts | 50 +++++++++++++++++++ 5 files changed, 231 insertions(+) create mode 100644 testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt create mode 100644 testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols create mode 100644 testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json create mode 100644 testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types create mode 100644 testdata/tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt new file mode 100644 index 00000000000..bb8defb2c2a --- /dev/null +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt @@ -0,0 +1,49 @@ +/node_modules/pkg/cjs.d.ts(6,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'expectedCondition' must be of type '"import"', but here has type '"default"'. + + +==== /index.ts (0 errors) ==== + // The automatic type directive "pkg" from @types should resolve to esm.d.mts + // because bundler resolution uses the "import" condition. + // If the wrong file is resolved, we'll get a type error due to conflicting declarations. + import type { PkgType } from "pkg"; + + // This should work if esm.d.mts is correctly resolved + const x: PkgType = { esm: true }; + +==== /node_modules/pkg/package.json (0 errors) ==== + { + "name": "pkg", + "version": "1.0.0", + "exports": { + ".": { + "import": { + "types": "./esm.d.mts" + }, + "default": { + "types": "./cjs.d.ts" + } + } + } + } + +==== /node_modules/pkg/esm.d.mts (0 errors) ==== + // This file should be resolved when using bundler resolution with "import" condition + export interface PkgType { + esm: true; + } + declare global { + var expectedCondition: "import"; + } + +==== /node_modules/pkg/cjs.d.ts (1 errors) ==== + // This file should NOT be resolved - it's the "default" condition fallback + export interface PkgType { + cjs: true; // Different shape - will cause error if wrong file is used + } + declare global { + var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded + ~~~~~~~~~~~~~~~~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'expectedCondition' must be of type '"import"', but here has type '"default"'. +!!! related TS6203 /node_modules/pkg/esm.d.mts:6:9: 'expectedCondition' was also declared here. + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols new file mode 100644 index 00000000000..42a10aaba14 --- /dev/null +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts] //// + +=== /index.ts === +// The automatic type directive "pkg" from @types should resolve to esm.d.mts +// because bundler resolution uses the "import" condition. +// If the wrong file is resolved, we'll get a type error due to conflicting declarations. +import type { PkgType } from "pkg"; +>PkgType : Symbol(PkgType, Decl(index.ts, 3, 13)) + +// This should work if esm.d.mts is correctly resolved +const x: PkgType = { esm: true }; +>x : Symbol(x, Decl(index.ts, 6, 5)) +>PkgType : Symbol(PkgType, Decl(index.ts, 3, 13)) +>esm : Symbol(esm, Decl(index.ts, 6, 20)) + +=== /node_modules/pkg/esm.d.mts === +// This file should be resolved when using bundler resolution with "import" condition +export interface PkgType { +>PkgType : Symbol(PkgType, Decl(esm.d.mts, 0, 0)) + + esm: true; +>esm : Symbol(PkgType.esm, Decl(esm.d.mts, 1, 26)) +} +declare global { +>global : Symbol(global, Decl(esm.d.mts, 3, 1)) + + var expectedCondition: "import"; +>expectedCondition : Symbol(expectedCondition, Decl(esm.d.mts, 5, 7), Decl(cjs.d.ts, 5, 7)) +} + +=== /node_modules/pkg/cjs.d.ts === +// This file should NOT be resolved - it's the "default" condition fallback +export interface PkgType { +>PkgType : Symbol(PkgType, Decl(cjs.d.ts, 0, 0)) + + cjs: true; // Different shape - will cause error if wrong file is used +>cjs : Symbol(PkgType.cjs, Decl(cjs.d.ts, 1, 26)) +} +declare global { +>global : Symbol(global, Decl(cjs.d.ts, 3, 1)) + + var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded +>expectedCondition : Symbol(expectedCondition, Decl(esm.d.mts, 5, 7), Decl(cjs.d.ts, 5, 7)) +} + diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json new file mode 100644 index 00000000000..acc94452cc7 --- /dev/null +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json @@ -0,0 +1,43 @@ +======== Resolving module 'pkg' from '/index.ts'. ======== +Explicitly specified module resolution kind: 'Bundler'. +Resolving in CJS mode with conditions 'import', 'types'. +File '/package.json' does not exist. +Loading module 'pkg' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON. +Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration. +Found 'package.json' at '/node_modules/pkg/package.json'. +Entering conditional exports. +Matched 'exports' condition 'import'. +Entering conditional exports. +Matched 'exports' condition 'types'. +Using 'exports' subpath '.' with target './esm.d.mts'. +File '/node_modules/pkg/esm.d.mts' exists - use it as a name resolution result. +'package.json' does not have a 'peerDependencies' field. +Resolved under condition 'types'. +Exiting conditional exports. +Resolved under condition 'import'. +Exiting conditional exports. +Resolving real path for '/node_modules/pkg/esm.d.mts', result '/node_modules/pkg/esm.d.mts'. +======== Module name 'pkg' was successfully resolved to '/node_modules/pkg/esm.d.mts' with Package ID 'pkg/esm.d.mts@1.0.0'. ======== +======== Resolving type reference directive 'pkg', 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'. +Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it. +Directory '/node_modules/@types' does not exist, skipping all lookups in it. +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. +Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it. +File '/node_modules/pkg/package.json' exists according to earlier cached lookups. +Entering conditional exports. +Saw non-matching condition 'import'. +Matched 'exports' condition 'default'. +Entering conditional exports. +Matched 'exports' condition 'types'. +Using 'exports' subpath '.' with target './cjs.d.ts'. +File '/node_modules/pkg/cjs.d.ts' exists - use it as a name resolution result. +'package.json' does not have a 'peerDependencies' field. +Resolved under condition 'types'. +Exiting conditional exports. +Resolved under condition 'default'. +Exiting conditional exports. +Resolving real path for '/node_modules/pkg/cjs.d.ts', result '/node_modules/pkg/cjs.d.ts'. +======== Type reference directive 'pkg' was successfully resolved to '/node_modules/pkg/cjs.d.ts' with Package ID 'pkg/cjs.d.ts@1.0.0', primary: false. ======== diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types new file mode 100644 index 00000000000..0dcf76176e7 --- /dev/null +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts] //// + +=== /index.ts === +// The automatic type directive "pkg" from @types should resolve to esm.d.mts +// because bundler resolution uses the "import" condition. +// If the wrong file is resolved, we'll get a type error due to conflicting declarations. +import type { PkgType } from "pkg"; +>PkgType : PkgType + +// This should work if esm.d.mts is correctly resolved +const x: PkgType = { esm: true }; +>x : PkgType +>{ esm: true } : { esm: true; } +>esm : true +>true : true + +=== /node_modules/pkg/esm.d.mts === +// This file should be resolved when using bundler resolution with "import" condition +export interface PkgType { + esm: true; +>esm : true +>true : true +} +declare global { +>global : typeof global + + var expectedCondition: "import"; +>expectedCondition : "import" +} + +=== /node_modules/pkg/cjs.d.ts === +// This file should NOT be resolved - it's the "default" condition fallback +export interface PkgType { + cjs: true; // Different shape - will cause error if wrong file is used +>cjs : true +>true : true +} +declare global { +>global : typeof global + + var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded +>expectedCondition : "import" +} + diff --git a/testdata/tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts b/testdata/tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts new file mode 100644 index 00000000000..57b13ff5a96 --- /dev/null +++ b/testdata/tests/cases/compiler/automaticTypeDirectiveResolutionBundler.ts @@ -0,0 +1,50 @@ +// @noImplicitReferences: true +// @module: esnext +// @moduleResolution: bundler +// @types: pkg +// @traceResolution: true +// @noEmit: true +// @strict: true + +// @filename: /node_modules/pkg/package.json +{ + "name": "pkg", + "version": "1.0.0", + "exports": { + ".": { + "import": { + "types": "./esm.d.mts" + }, + "default": { + "types": "./cjs.d.ts" + } + } + } +} + +// @filename: /node_modules/pkg/esm.d.mts +// This file should be resolved when using bundler resolution with "import" condition +export interface PkgType { + esm: true; +} +declare global { + var expectedCondition: "import"; +} + +// @filename: /node_modules/pkg/cjs.d.ts +// This file should NOT be resolved - it's the "default" condition fallback +export interface PkgType { + cjs: true; // Different shape - will cause error if wrong file is used +} +declare global { + var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded +} + +// @filename: /index.ts +// The automatic type directive "pkg" from @types should resolve to esm.d.mts +// because bundler resolution uses the "import" condition. +// If the wrong file is resolved, we'll get a type error due to conflicting declarations. +import type { PkgType } from "pkg"; + +// This should work if esm.d.mts is correctly resolved +const x: PkgType = { esm: true }; From 2734d5eb969158f9b14f4c2218456716f62247f8 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:54:45 -0800 Subject: [PATCH 2/2] Fix porting bug in resolveAutomaticTypeDirectives --- internal/compiler/fileloader.go | 4 +- ...cTypeDirectiveResolutionBundler.errors.txt | 49 ------------------- ...aticTypeDirectiveResolutionBundler.symbols | 17 +------ ...cTypeDirectiveResolutionBundler.trace.json | 13 +++-- ...omaticTypeDirectiveResolutionBundler.types | 14 ------ 5 files changed, 10 insertions(+), 87 deletions(-) delete mode 100644 testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt diff --git a/internal/compiler/fileloader.go b/internal/compiler/fileloader.go index ee2daa137f0..c4836b72364 100644 --- a/internal/compiler/fileloader.go +++ b/internal/compiler/fileloader.go @@ -180,7 +180,9 @@ func (p *fileLoader) resolveAutomaticTypeDirectives(containingFileName string) ( toParse = make([]resolvedRef, 0, len(automaticTypeDirectiveNames)) typeResolutionsInFile = make(module.ModeAwareCache[*module.ResolvedTypeReferenceDirective], len(automaticTypeDirectiveNames)) for _, name := range automaticTypeDirectiveNames { - resolutionMode := core.ModuleKindNodeNext + // Under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode. + // Under bundler module resolution, this also triggers the "import" condition to be used. + resolutionMode := core.ResolutionModeNone resolved, trace := p.resolver.ResolveTypeReferenceDirective(name, containingFileName, resolutionMode, nil) typeResolutionsInFile[module.ModeAwareCacheKey{Name: name, Mode: resolutionMode}] = resolved typeResolutionsTrace = append(typeResolutionsTrace, trace...) diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt deleted file mode 100644 index bb8defb2c2a..00000000000 --- a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.errors.txt +++ /dev/null @@ -1,49 +0,0 @@ -/node_modules/pkg/cjs.d.ts(6,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'expectedCondition' must be of type '"import"', but here has type '"default"'. - - -==== /index.ts (0 errors) ==== - // The automatic type directive "pkg" from @types should resolve to esm.d.mts - // because bundler resolution uses the "import" condition. - // If the wrong file is resolved, we'll get a type error due to conflicting declarations. - import type { PkgType } from "pkg"; - - // This should work if esm.d.mts is correctly resolved - const x: PkgType = { esm: true }; - -==== /node_modules/pkg/package.json (0 errors) ==== - { - "name": "pkg", - "version": "1.0.0", - "exports": { - ".": { - "import": { - "types": "./esm.d.mts" - }, - "default": { - "types": "./cjs.d.ts" - } - } - } - } - -==== /node_modules/pkg/esm.d.mts (0 errors) ==== - // This file should be resolved when using bundler resolution with "import" condition - export interface PkgType { - esm: true; - } - declare global { - var expectedCondition: "import"; - } - -==== /node_modules/pkg/cjs.d.ts (1 errors) ==== - // This file should NOT be resolved - it's the "default" condition fallback - export interface PkgType { - cjs: true; // Different shape - will cause error if wrong file is used - } - declare global { - var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded - ~~~~~~~~~~~~~~~~~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'expectedCondition' must be of type '"import"', but here has type '"default"'. -!!! related TS6203 /node_modules/pkg/esm.d.mts:6:9: 'expectedCondition' was also declared here. - } - \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols index 42a10aaba14..025316de563 100644 --- a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.symbols @@ -25,21 +25,6 @@ declare global { >global : Symbol(global, Decl(esm.d.mts, 3, 1)) var expectedCondition: "import"; ->expectedCondition : Symbol(expectedCondition, Decl(esm.d.mts, 5, 7), Decl(cjs.d.ts, 5, 7)) -} - -=== /node_modules/pkg/cjs.d.ts === -// This file should NOT be resolved - it's the "default" condition fallback -export interface PkgType { ->PkgType : Symbol(PkgType, Decl(cjs.d.ts, 0, 0)) - - cjs: true; // Different shape - will cause error if wrong file is used ->cjs : Symbol(PkgType.cjs, Decl(cjs.d.ts, 1, 26)) -} -declare global { ->global : Symbol(global, Decl(cjs.d.ts, 3, 1)) - - var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded ->expectedCondition : Symbol(expectedCondition, Decl(esm.d.mts, 5, 7), Decl(cjs.d.ts, 5, 7)) +>expectedCondition : Symbol(expectedCondition, Decl(esm.d.mts, 5, 7)) } diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json index acc94452cc7..87041e80987 100644 --- a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.trace.json @@ -28,16 +28,15 @@ Directory '/.src/node_modules' does not exist, skipping all lookups in it. Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it. File '/node_modules/pkg/package.json' exists according to earlier cached lookups. Entering conditional exports. -Saw non-matching condition 'import'. -Matched 'exports' condition 'default'. +Matched 'exports' condition 'import'. Entering conditional exports. Matched 'exports' condition 'types'. -Using 'exports' subpath '.' with target './cjs.d.ts'. -File '/node_modules/pkg/cjs.d.ts' exists - use it as a name resolution result. +Using 'exports' subpath '.' with target './esm.d.mts'. +File '/node_modules/pkg/esm.d.mts' exists - use it as a name resolution result. 'package.json' does not have a 'peerDependencies' field. Resolved under condition 'types'. Exiting conditional exports. -Resolved under condition 'default'. +Resolved under condition 'import'. Exiting conditional exports. -Resolving real path for '/node_modules/pkg/cjs.d.ts', result '/node_modules/pkg/cjs.d.ts'. -======== Type reference directive 'pkg' was successfully resolved to '/node_modules/pkg/cjs.d.ts' with Package ID 'pkg/cjs.d.ts@1.0.0', primary: false. ======== +Resolving real path for '/node_modules/pkg/esm.d.mts', result '/node_modules/pkg/esm.d.mts'. +======== Type reference directive 'pkg' was successfully resolved to '/node_modules/pkg/esm.d.mts' with Package ID 'pkg/esm.d.mts@1.0.0', primary: false. ======== diff --git a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types index 0dcf76176e7..1f071869feb 100644 --- a/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types +++ b/testdata/baselines/reference/compiler/automaticTypeDirectiveResolutionBundler.types @@ -28,17 +28,3 @@ declare global { >expectedCondition : "import" } -=== /node_modules/pkg/cjs.d.ts === -// This file should NOT be resolved - it's the "default" condition fallback -export interface PkgType { - cjs: true; // Different shape - will cause error if wrong file is used ->cjs : true ->true : true -} -declare global { ->global : typeof global - - var expectedCondition: "default"; // Conflicts with esm.d.mts if both are loaded ->expectedCondition : "import" -} -