Skip to content

Adding an outExtension option to control the file extension of emitted files #54583

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

Closed
wants to merge 6 commits into from
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
16 changes: 16 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import {
normalizeSlashes,
NumericLiteral,
ObjectLiteralExpression,
OutExtensionKind,
ParseConfigHost,
ParsedCommandLine,
parseJsonText,
Expand Down Expand Up @@ -696,6 +697,21 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
category: Diagnostics.Emit,
description: Diagnostics.Specify_an_output_folder_for_all_emitted_files,
},
{
name: "outExtension",
type: new Map(Object.entries({
input: OutExtensionKind.InferFromInput,
module: OutExtensionKind.InferFromModule,
js: OutExtensionKind.Js,
cjs: OutExtensionKind.Cjs,
mjs: OutExtensionKind.Mjs,
})),
defaultValueDescription: "input",
affectsEmit: true,
affectsBuildInfo: true,
category: Diagnostics.Emit,
description: Diagnostics.Specify_the_output_extension_for_all_emitted_files_input_will_determine_extension_based_on_the_extension_of_the_input_file_module_will_determine_extension_based_on_the_module_option,
},
{
name: "rootDir",
type: "string",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -6099,6 +6099,10 @@
"category": "Message",
"code": 6718
},
"Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option.": {
"category": "Message",
"code": 6719
},
"Default catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
"code": 6803
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,14 @@ function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) {
export function getOutputExtension(fileName: string, options: CompilerOptions): Extension {
return fileExtensionIs(fileName, Extension.Json) ? Extension.Json :
options.jsx === JsxEmit.Preserve && fileExtensionIsOneOf(fileName, [Extension.Jsx, Extension.Tsx]) ? Extension.Jsx :
options.outExtension === ts.OutExtensionKind.InferFromModule ? (
options.module === ModuleKind.CommonJS ? Extension.Cjs :
options.module && options.module >= ModuleKind.ES2015 && options.module <= ModuleKind.ESNext ? Extension.Mjs :
Extension.Js
) :
options.outExtension === ts.OutExtensionKind.Cjs ? Extension.Cjs :
options.outExtension === ts.OutExtensionKind.Mjs ? Extension.Mjs :
options.outExtension === ts.OutExtensionKind.Js ? Extension.Js :
fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Mjs]) ? Extension.Mjs :
fileExtensionIsOneOf(fileName, [Extension.Cts, Extension.Cjs]) ? Extension.Cjs :
Extension.Js;
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7171,6 +7171,7 @@ export interface CompilerOptions {
noUncheckedIndexedAccess?: boolean;
out?: string;
outDir?: string;
outExtension?: OutExtensionKind;
outFile?: string;
paths?: MapLike<string[]>;
/**
Expand Down Expand Up @@ -7709,6 +7710,14 @@ export const enum Extension {
Dcts = ".d.cts",
}

export const enum OutExtensionKind {
InferFromInput = 0,
InferFromModule = 1,
Js = 2,
Cjs = 3,
Mjs = 4,
}

export interface ResolvedModuleWithFailedLookupLocations {
readonly resolvedModule: ResolvedModuleFull | undefined;
/** @internal */
Expand Down
8 changes: 8 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7231,6 +7231,7 @@ declare namespace ts {
noUncheckedIndexedAccess?: boolean;
out?: string;
outDir?: string;
outExtension?: OutExtensionKind;
outFile?: string;
paths?: MapLike<string[]>;
preserveConstEnums?: boolean;
Expand Down Expand Up @@ -7468,6 +7469,13 @@ declare namespace ts {
Cts = ".cts",
Dcts = ".d.cts"
}
enum OutExtensionKind {
InferFromInput = 0,
InferFromModule = 1,
Js = 2,
Cjs = 3,
Mjs = 4
}
interface ResolvedModuleWithFailedLookupLocations {
readonly resolvedModule: ResolvedModuleFull | undefined;
}
Expand Down
8 changes: 8 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3178,6 +3178,7 @@ declare namespace ts {
noUncheckedIndexedAccess?: boolean;
out?: string;
outDir?: string;
outExtension?: OutExtensionKind;
outFile?: string;
paths?: MapLike<string[]>;
preserveConstEnums?: boolean;
Expand Down Expand Up @@ -3415,6 +3416,13 @@ declare namespace ts {
Cts = ".cts",
Dcts = ".d.cts"
}
enum OutExtensionKind {
InferFromInput = 0,
InferFromModule = 1,
Js = 2,
Cjs = 3,
Mjs = 4
}
interface ResolvedModuleWithFailedLookupLocations {
readonly resolvedModule: ResolvedModuleFull | undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "outExtension": "input", /* Specify the output extension for all emitted files. 'input' will determine extension based on the extension of the input file. 'module' will determine extension based on the `module` option. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"outExtension": "input"
}
}
51 changes: 51 additions & 0 deletions tests/baselines/reference/outExtensionCjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//// [tests/cases/compiler/outExtensionCjs.ts] ////

//// [input-1.ts]
export const ts = "foo";

//// [input-2.mts]
export const mts = "foo";

//// [input-3.cts]
export const cts = "foo";

//// [input-4.js]
export const js = "foo";

//// [input-5.mjs]
export const mjs = "foo";

//// [input-6.cjs]
export const cjs = "foo";


//// [input-1.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ts = void 0;
exports.ts = "foo";
//// [input-2.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mts = void 0;
exports.mts = "foo";
//// [input-3.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cts = void 0;
exports.cts = "foo";
//// [input-4.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.js = void 0;
exports.js = "foo";
//// [input-5.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mjs = void 0;
exports.mjs = "foo";
//// [input-6.cjs]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cjs = void 0;
exports.cjs = "foo";
24 changes: 24 additions & 0 deletions tests/baselines/reference/outExtensionCjs.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
=== tests/cases/compiler/input-1.ts ===
export const ts = "foo";
>ts : Symbol(ts, Decl(input-1.ts, 0, 12))

=== tests/cases/compiler/input-2.mts ===
export const mts = "foo";
>mts : Symbol(mts, Decl(input-2.mts, 0, 12))

=== tests/cases/compiler/input-3.cts ===
export const cts = "foo";
>cts : Symbol(cts, Decl(input-3.cts, 0, 12))

=== tests/cases/compiler/input-4.js ===
export const js = "foo";
>js : Symbol(js, Decl(input-4.js, 0, 12))

=== tests/cases/compiler/input-5.mjs ===
export const mjs = "foo";
>mjs : Symbol(mjs, Decl(input-5.mjs, 0, 12))

=== tests/cases/compiler/input-6.cjs ===
export const cjs = "foo";
>cjs : Symbol(cjs, Decl(input-6.cjs, 0, 12))

30 changes: 30 additions & 0 deletions tests/baselines/reference/outExtensionCjs.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
=== tests/cases/compiler/input-1.ts ===
export const ts = "foo";
>ts : "foo"
>"foo" : "foo"

=== tests/cases/compiler/input-2.mts ===
export const mts = "foo";
>mts : "foo"
>"foo" : "foo"

=== tests/cases/compiler/input-3.cts ===
export const cts = "foo";
>cts : "foo"
>"foo" : "foo"

=== tests/cases/compiler/input-4.js ===
export const js = "foo";
>js : "foo"
>"foo" : "foo"

=== tests/cases/compiler/input-5.mjs ===
export const mjs = "foo";
>mjs : "foo"
>"foo" : "foo"

=== tests/cases/compiler/input-6.cjs ===
export const cjs = "foo";
>cjs : "foo"
>"foo" : "foo"

Loading