Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion internal/modulespecifiers/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ func GetAllowedEndingsInPreferredOrder(
moduleResolution := compilerOptions.GetModuleResolutionKind()
moduleResolutionIsNodeNext := core.ModuleResolutionKindNode16 <= moduleResolution && moduleResolution <= core.ModuleResolutionKindNodeNext
allowImportingTsExtension := shouldAllowImportingTsExtension(compilerOptions, importingSourceFile.FileName())
if syntaxImpliedNodeFormat == core.ResolutionModeESM && moduleResolutionIsNodeNext {
// TypeScript uses `(syntaxImpliedNodeFormat ?? impliedNodeFormat)` here - fall back to the
// file's default resolution mode when no syntax-implied mode is given.
effectiveSyntaxMode := syntaxImpliedNodeFormat
if effectiveSyntaxMode == core.ResolutionModeNone {
effectiveSyntaxMode = resolutionMode
}
if effectiveSyntaxMode == core.ResolutionModeESM && moduleResolutionIsNodeNext {
if allowImportingTsExtension {
return []ModuleSpecifierEnding{ModuleSpecifierEndingTsExtension, ModuleSpecifierEndingJsExtension}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//// [tests/cases/compiler/declarationEmitImportSpecifierWithTsExtensionRelativeImport.ts] ////

//// [package.json]
{ "type": "module" }

//// [package.json]
{ "name": "mylib", "version": "1.0.0", "main": "./lib/index.js" }

//// [Box.d.ts]
export interface Box<T> { readonly value: T }
export declare function box<T>(value: T): Box<T>;

//// [helper.ts]
import * as B from 'mylib/lib/Box.js';
export const inner = B.box('hello');

//// [mod.ts]
import { inner } from './helper.ts';
export const out = inner;




//// [helper.d.ts]
import * as B from 'mylib/lib/Box.js';
export declare const inner: B.Box<string>;
//// [mod.d.ts]
export declare const out: import("mylib/lib/Box.js").Box<string>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//// [tests/cases/compiler/declarationEmitImportSpecifierWithTsExtensionRelativeImport.ts] ////

=== /node_modules/mylib/lib/Box.d.ts ===
export interface Box<T> { readonly value: T }
>Box : Symbol(Box, Decl(Box.d.ts, 0, 0))
>T : Symbol(T, Decl(Box.d.ts, 0, 21))
>value : Symbol(Box.value, Decl(Box.d.ts, 0, 25))
>T : Symbol(T, Decl(Box.d.ts, 0, 21))

export declare function box<T>(value: T): Box<T>;
>box : Symbol(box, Decl(Box.d.ts, 0, 45))
>T : Symbol(T, Decl(Box.d.ts, 1, 28))
>value : Symbol(value, Decl(Box.d.ts, 1, 31))
>T : Symbol(T, Decl(Box.d.ts, 1, 28))
>Box : Symbol(Box, Decl(Box.d.ts, 0, 0))
>T : Symbol(T, Decl(Box.d.ts, 1, 28))

=== /helper.ts ===
import * as B from 'mylib/lib/Box.js';
>B : Symbol(B, Decl(helper.ts, 0, 6))

export const inner = B.box('hello');
>inner : Symbol(inner, Decl(helper.ts, 1, 12))
>B.box : Symbol(B.box, Decl(Box.d.ts, 0, 45))
>B : Symbol(B, Decl(helper.ts, 0, 6))
>box : Symbol(B.box, Decl(Box.d.ts, 0, 45))

=== /mod.ts ===
import { inner } from './helper.ts';
>inner : Symbol(inner, Decl(mod.ts, 0, 8))

export const out = inner;
>out : Symbol(out, Decl(mod.ts, 1, 12))
>inner : Symbol(inner, Decl(mod.ts, 0, 8))

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//// [tests/cases/compiler/declarationEmitImportSpecifierWithTsExtensionRelativeImport.ts] ////

=== /node_modules/mylib/lib/Box.d.ts ===
export interface Box<T> { readonly value: T }
>value : T

export declare function box<T>(value: T): Box<T>;
>box : <T>(value: T) => Box<T>
>value : T

=== /helper.ts ===
import * as B from 'mylib/lib/Box.js';
>B : typeof B

export const inner = B.box('hello');
>inner : B.Box<string>
>B.box('hello') : B.Box<string>
>B.box : <T>(value: T) => B.Box<T>
>B : typeof B
>box : <T>(value: T) => B.Box<T>
>'hello' : "hello"

=== /mod.ts ===
import { inner } from './helper.ts';
>inner : import("mylib/lib/Box.js").Box<string>

export const out = inner;
>out : import("mylib/lib/Box.js").Box<string>
>inner : import("mylib/lib/Box.js").Box<string>

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @module: nodenext
// @declaration: true
// @emitDeclarationOnly: true
// @allowImportingTsExtensions: true

// Regression test for https://github.com/microsoft/typescript-go/issues/4616
// When a file uses `.ts` extension relative imports with allowImportingTsExtensions,
// declaration emit should preserve `.js` extensions on non-relative (node_modules) imports.

// @Filename: /package.json
{ "type": "module" }

// @Filename: /node_modules/mylib/package.json
{ "name": "mylib", "version": "1.0.0", "main": "./lib/index.js" }

// @Filename: /node_modules/mylib/lib/Box.d.ts
export interface Box<T> { readonly value: T }
export declare function box<T>(value: T): Box<T>;

// @Filename: /helper.ts
import * as B from 'mylib/lib/Box.js';
export const inner = B.box('hello');

// @Filename: /mod.ts
import { inner } from './helper.ts';
export const out = inner;