-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Add a new compiler option moduleSuffixes
to expand the node module resolver's search algorithm
#48189
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
Add a new compiler option moduleSuffixes
to expand the node module resolver's search algorithm
#48189
Changes from 7 commits
6fc83e7
866ab7b
6fde83e
0d45cb6
c11bea7
407f33f
682b687
5a6026f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -884,6 +884,18 @@ namespace ts { | |
description: Diagnostics.Allow_accessing_UMD_globals_from_modules, | ||
defaultValueDescription: false, | ||
}, | ||
{ | ||
name: "moduleSuffixes", | ||
type: "list", | ||
element: { | ||
name: "suffix", | ||
type: "string", | ||
}, | ||
listPreserveFalsyValues: true, | ||
affectsModuleResolution: true, | ||
category: Diagnostics.Modules, | ||
description: Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module, | ||
}, | ||
|
||
// Source Maps | ||
{ | ||
|
@@ -1449,7 +1461,7 @@ namespace ts { | |
case "number": | ||
return mapDefined(values, v => validateJsonOptionValue(opt.element, parseInt(v), errors)); | ||
case "string": | ||
return mapDefined(values, v => validateJsonOptionValue(opt.element, v || "", errors)); | ||
return mapDefined(values, v => validateJsonOptionValue(opt.element, opt.listPreserveFalsyValues ? v : (v || ""), errors)); | ||
default: | ||
return mapDefined(values, v => parseCustomTypeOption(opt.element as CommandLineOptionOfCustomType, v, errors)); | ||
} | ||
|
@@ -3192,7 +3204,7 @@ namespace ts { | |
if (option.type === "list") { | ||
const listOption = option; | ||
if (listOption.element.isFilePath || !isString(listOption.element.type)) { | ||
return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => !!v) as CompilerOptionsValue; | ||
return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => listOption.listPreserveFalsyValues ? true : !!v) as CompilerOptionsValue; | ||
} | ||
return value; | ||
} | ||
|
@@ -3233,7 +3245,7 @@ namespace ts { | |
} | ||
|
||
function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: readonly any[], basePath: string, errors: Push<Diagnostic>): any[] { | ||
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v); | ||
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => option.listPreserveFalsyValues ? true : !!v); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think instead of this we should just check if option is defined and get rid of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would change the behavior of other lists, like To be clear what you're looking for, the filter condition would become There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sheetalkamat Would you like to make this change, or is the risk of impacting existing projects too great? Please advise. |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//// [tests/cases/compiler/moduleResolutionWithSuffixes_empty.ts] //// | ||
|
||
//// [index.ts] | ||
import { base } from "./foo"; | ||
//// [foo.ts] | ||
export function base() {} | ||
|
||
|
||
//// [foo.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.base = void 0; | ||
function base() { } | ||
exports.base = base; | ||
//// [index.js] | ||
"use strict"; | ||
exports.__esModule = true; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : Symbol(base, Decl(index.ts, 0, 8)) | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : Symbol(base, Decl(foo.ts, 0, 0)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
"======== Resolving module './foo' from '/index.ts'. ========", | ||
"Explicitly specified module resolution kind: 'NodeJs'.", | ||
"Loading module as file / folder, candidate module location '/foo', target file type 'TypeScript'.", | ||
"File '/foo.ts' exist - use it as a name resolution result.", | ||
"======== Module name './foo' was successfully resolved to '/foo.ts'. ========" | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : () => void | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : () => void | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//// [tests/cases/compiler/moduleResolutionWithSuffixes_notSpecified.ts] //// | ||
|
||
//// [index.ts] | ||
import { base } from "./foo"; | ||
//// [foo.ts] | ||
export function base() {} | ||
|
||
|
||
//// [foo.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.base = void 0; | ||
function base() { } | ||
exports.base = base; | ||
//// [index.js] | ||
"use strict"; | ||
exports.__esModule = true; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : Symbol(base, Decl(index.ts, 0, 8)) | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : Symbol(base, Decl(foo.ts, 0, 0)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
"======== Resolving module './foo' from '/index.ts'. ========", | ||
"Explicitly specified module resolution kind: 'NodeJs'.", | ||
"Loading module as file / folder, candidate module location '/foo', target file type 'TypeScript'.", | ||
"File '/foo.ts' exist - use it as a name resolution result.", | ||
"======== Module name './foo' was successfully resolved to '/foo.ts'. ========" | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : () => void | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : () => void | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
//// [tests/cases/compiler/moduleResolutionWithSuffixes_one.ts] //// | ||
|
||
//// [index.ts] | ||
import { ios } from "./foo"; | ||
//// [foo.ios.ts] | ||
export function ios() {} | ||
//// [foo.ts] | ||
export function base() {} | ||
|
||
|
||
//// [foo.ios.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.ios = void 0; | ||
function ios() { } | ||
exports.ios = ios; | ||
//// [index.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
//// [foo.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.base = void 0; | ||
function base() { } | ||
exports.base = base; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
=== /index.ts === | ||
import { ios } from "./foo"; | ||
>ios : Symbol(ios, Decl(index.ts, 0, 8)) | ||
|
||
=== /foo.ios.ts === | ||
export function ios() {} | ||
>ios : Symbol(ios, Decl(foo.ios.ts, 0, 0)) | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : Symbol(base, Decl(foo.ts, 0, 0)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
"======== Resolving module './foo' from '/index.ts'. ========", | ||
"Explicitly specified module resolution kind: 'NodeJs'.", | ||
"Loading module as file / folder, candidate module location '/foo', target file type 'TypeScript'.", | ||
"File '/foo.ios.ts' exist - use it as a name resolution result.", | ||
"======== Module name './foo' was successfully resolved to '/foo.ios.ts'. ========" | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
=== /index.ts === | ||
import { ios } from "./foo"; | ||
>ios : () => void | ||
|
||
=== /foo.ios.ts === | ||
export function ios() {} | ||
>ios : () => void | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : () => void | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//// [tests/cases/compiler/moduleResolutionWithSuffixes_oneBlank.ts] //// | ||
|
||
//// [index.ts] | ||
import { base } from "./foo"; | ||
//// [foo.ts] | ||
export function base() {} | ||
|
||
|
||
//// [foo.js] | ||
"use strict"; | ||
exports.__esModule = true; | ||
exports.base = void 0; | ||
function base() { } | ||
exports.base = base; | ||
//// [index.js] | ||
"use strict"; | ||
exports.__esModule = true; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : Symbol(base, Decl(index.ts, 0, 8)) | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : Symbol(base, Decl(foo.ts, 0, 0)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
"======== Resolving module './foo' from '/index.ts'. ========", | ||
"Explicitly specified module resolution kind: 'NodeJs'.", | ||
"Loading module as file / folder, candidate module location '/foo', target file type 'TypeScript'.", | ||
"File '/foo.ts' exist - use it as a name resolution result.", | ||
"======== Module name './foo' was successfully resolved to '/foo.ts'. ========" | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
=== /index.ts === | ||
import { base } from "./foo"; | ||
>base : () => void | ||
|
||
=== /foo.ts === | ||
export function base() {} | ||
>base : () => void | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/index.ts(1,21): error TS2307: Cannot find module './foo' or its corresponding type declarations. | ||
|
||
|
||
==== /tsconfig.json (0 errors) ==== | ||
// moduleSuffixes has one entry but there isn't a matching file. Module resolution should fail. | ||
|
||
{ | ||
"compilerOptions": { | ||
"moduleResolution": "node", | ||
"traceResolution": true, | ||
"moduleSuffixes": [".ios"] | ||
} | ||
} | ||
|
||
==== /index.ts (1 errors) ==== | ||
import { ios } from "./foo"; | ||
~~~~~~~ | ||
!!! error TS2307: Cannot find module './foo' or its corresponding type declarations. | ||
==== /foo.ts (0 errors) ==== | ||
export function base() {} | ||
|
Uh oh!
There was an error while loading. Please reload this page.