输出
declaration
为项目中的每个 TypeScript 或 JavaScript 文件生成 .d.ts 文件。 这些 .d.ts 文件是描述模块外部 API 的类型定义文件。 有了 .d.ts 文件,像 TypeScript 这样的工具可以为无类型代码提供智能感知和准确的类型。
当 declaration 设置为 true 时,使用此 TypeScript 代码运行编译器:
将生成一个如下的 index.js 文件:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.helloWorld = void 0;
exports.helloWorld = "hi";
Try以及对应的 helloWorld.d.ts:
当处理 JavaScript 文件的 .d.ts 文件时,你可能希望使用 emitDeclarationOnly 或使用 outDir 来确保 JavaScript 文件不会被覆盖。
declarationDir
发布版本: 2.0
相关: declaration
提供一种配置声明文件输出根目录的方法。
example
├── index.ts
├── package.json
└── tsconfig.json使用此 tsconfig.json:
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./types"
}
}会将 index.ts 的 d.ts 文件放置在 types 文件夹中:
example
├── index.js
├── index.ts
├── package.json
├── tsconfig.json
└── types
└── index.d.tsdeclarationMap
- 发布版本: 2.9
为 .d.ts 文件生成源映射,映射回原始的 .ts 源文件。 这将允许像 VS Code 这样的编辑器在使用“转到定义”等功能时跳转到原始的 .ts 文件。
如果你正在使用项目引用,强烈建议你开启此选项。
downlevelIteration
发布版本: 2.3
相关: importHelpers
降级是 TypeScript 将代码转译为旧版 JavaScript 的术语。 此标志旨在支持更准确地实现现代 JavaScript 在旧版 JavaScript 运行时中如何迭代新概念。
ECMAScript 6 添加了几个新的迭代原语:for / of 循环 (for (el of arr))、数组展开 ([a, ...b])、参数展开 (fn(...args)) 和 Symbol.iterator。 如果存在 Symbol.iterator 实现,downlevelIteration 允许这些迭代原语在 ES5 环境中被更准确地使用。
示例:对 for / of 的影响
使用此 TypeScript 代码:
如果未启用 downlevelIteration,任何对象上的 for / of 循环都会降级为传统的 for 循环:
"use strict";
var str = "Hello!";
for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
var s = str_1[_i];
console.log(s);
}
Try这通常是人们期望的,但它并不 100% 符合 ECMAScript 迭代协议。 某些字符串,如表情符号 (😜),具有 .length 为 2(甚至更多),但在 for-of 循环中应作为 1 个单位迭代。 有关更长的解释,请参阅 Jonathan New 的这篇博文。
当启用 downlevelIteration 时,TypeScript 将使用一个辅助函数来检查是否存在 Symbol.iterator 实现(原生或 polyfill)。 如果缺少此实现,将回退到基于索引的迭代。
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var e_1, _a;
var str = "Hello!";
try {
for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {
var s = str_1_1.value;
console.log(s);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
}
finally { if (e_1) throw e_1.error; }
}
Try你也可以通过 importHelpers 使用 tslib 来减少内联 JavaScript 的数量:
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var e_1, _a;
var str = "Hello!";
try {
for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {
var s = str_1_1.value;
console.log(s);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
}
finally { if (e_1) throw e_1.error; }
}
Try注意: 如果运行时中没有 Symbol.iterator,启用 downlevelIteration 并不会提高合规性。
示例:对数组展开的影响
这是一个数组展开:
// 创建一个新数组,其元素为 1 后跟 arr2 的元素
const arr = [1, ...arr2];根据描述,将其降级到 ES5 似乎很简单:
// 相同,对吧?
const arr = [1].concat(arr2);然而,在少数罕见情况下,这是可观察到的不同。
例如,如果源数组缺少一个或多个项目(包含空位),展开语法会将每个空项替换为 undefined,而 .concat 会保留它们不变。
// 创建一个索引 1 处缺失的数组
let arrayWithHole = ['a', , 'c'];
let spread = [...arrayWithHole];
let concatenated = [].concat(arrayWithHole);
console.log(arrayWithHole)
// [ 'a', <1 empty item>, 'c' ]
console.log(spread)
// [ 'a', undefined, 'c' ]
console.log(concatenated)
// [ 'a', <1 empty item>, 'c' ]与 for / of 一样,downlevelIteration 将使用 Symbol.iterator(如果存在)来更准确地模拟 ES6 行为。
emitBOM
- 发布版本: 1.0
控制 TypeScript 在写入输出文件时是否输出字节顺序标记 (BOM)。 某些运行时环境需要 BOM 才能正确解释 JavaScript 文件;其他运行时则要求不能存在 BOM。 除非你有理由更改它,否则默认值 false 通常是最好的。
emitDeclarationOnly
发布版本: 2.8
相关: declaration
仅输出 .d.ts 文件;不输出 .js 文件。
此设置有两种情况下很有用:
- 你使用 TypeScript 以外的转译器来生成 JavaScript。
- 你使用 TypeScript 仅为消费者生成
d.ts文件。
importHelpers
发布版本: 2.1
对于某些降级操作,TypeScript 会使用一些辅助代码,例如用于扩展类、展开数组或对象以及异步操作。 默认情况下,这些辅助函数会插入到使用它们的文件中。 如果同一个辅助函数在许多不同的模块中使用,这可能导致代码重复。
如果 importHelpers 标志开启,这些辅助函数将改为从 tslib 模块导入。 你需要确保在运行时可以导入 tslib 模块。 这仅影响模块;全局脚本文件不会尝试导入模块。
例如,使用此 TypeScript:
export function fn(arr: number[]) {
const arr2 = [1, ...arr];
}开启 downlevelIteration 且 importHelpers 仍为 false:
"use strict";
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fn = fn;
function fn(arr) {
var arr2 = __spreadArray([1], __read(arr), false);
}
Try然后同时开启 downlevelIteration 和 importHelpers:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fn = fn;
var tslib_1 = require("tslib");
function fn(arr) {
var arr2 = tslib_1.__spreadArray([1], tslib_1.__read(arr), false);
}
Try当你提供这些函数的自己的实现时,可以使用 noEmitHelpers。
inlineSourceMap
- 发布版本: 1.5
设置后,TypeScript 不会写出 .js.map 文件来提供源映射,而是将源映射内容嵌入到 .js 文件中。 虽然这会导致 JS 文件变大,但在某些场景下可能很方便。 例如,你可能想要在不允许提供 .map 文件的 Web 服务器上调试 JS 文件。
与 sourceMap 互斥。
例如,使用此 TypeScript:
const helloWorld = "hi";
console.log(helloWorld);转换为以下 JavaScript:
然后启用 inlineSourceMap 进行构建时,文件底部会有一个包含源映射的注释。
"use strict";
const helloWorld = "hi";
console.log(helloWorld);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ==TryinlineSources
- 发布版本: 1.5
设置后,TypeScript 会将 .ts 文件的原始内容作为嵌入字符串包含在源映射中(使用源映射的 sourcesContent 属性)。 这在与 inlineSourceMap 相同的情况下通常很有用。
需要设置 sourceMap 或 inlineSourceMap。
例如,使用此 TypeScript:
默认转换为以下 JavaScript:
然后启用 inlineSources 和 inlineSourceMap 进行构建时,文件底部会有一个包含源映射的注释。 注意,结尾与 inlineSourceMap 示例不同,因为源映射现在也包含了原始源代码。
"use strict";
const helloWorld = "hi";
console.log(helloWorld);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19TrymapRoot
- 发布版本: 1.0
指定调试器应定位映射文件的位置,而不是生成的位置。 此字符串在源映射中会被原样使用,例如:
{
"compilerOptions": {
"sourceMap": true,
"mapRoot": "https://my-website.com/debug/sourcemaps/"
}
}将声明 index.js 的源映射位于 https://my-website.com/debug/sourcemaps/index.js.map。
newLine
允许的值:
crlf,lf默认值:
lf发布版本: 1.5
指定输出文件时使用的行尾序列:'CRLF' (dos) 或 'LF' (unix)。
noEmit
- 发布版本: 1.5
不输出编译器输出文件,如 JavaScript 源代码、源映射或声明文件。
这为另一个工具(如 Babel 或 swc)处理将 TypeScript 文件转换为可在 JavaScript 环境中运行的文件提供了空间。
然后你可以将 TypeScript 用作提供编辑器集成和源代码类型检查的工具。
noEmitHelpers
发布版本: 1.5
相关: importHelpers
与使用 importHelpers 导入辅助函数不同,你可以为你使用的辅助函数在全局作用域中提供实现,并完全关闭辅助函数的输出。
例如,在 ES5 中使用此 async 函数需要一个类似 await 的函数和一个类似 generator 的函数来运行:
这会生成相当多的 JavaScript:
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
// 获取 API
return [2 /*return*/, {}];
});
}); };
Try通过此标志,可以使用你自己的全局变量来替换它们:
"use strict";
var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
// 获取 API
return [2 /*return*/, {}];
});
}); };
TrynoEmitOnError
- 发布版本: 1.4
如果报告了任何错误,则不输出编译器输出文件,如 JavaScript 源代码、源映射或声明文件。
默认值为 false,这使得在类似监视的环境中更容易使用 TypeScript,在这种环境中,你可能希望在确保所有错误都已解决之前,先在其他环境中看到代码更改的结果。
outDir
如果指定,.js(以及 .d.ts、.js.map 等)文件将输出到此目录。 原始源文件的目录结构会被保留;如果计算出的根不是你想要的,请参见 rootDir。
如果未指定,.js 文件将输出在与生成它们的 .ts 文件相同的目录中:
$ tsc
example
├── index.js
└── index.ts使用如下 tsconfig.json:
{
"compilerOptions": {
"outDir": "dist"
}
}使用这些设置运行 tsc 会将文件移动到指定的 dist 文件夹中:
$ tsc
example
├── dist
│ └── index.js
├── index.ts
└── tsconfig.jsonoutFile
如果指定,所有全局(非模块)文件将被连接成指定的单个输出文件。
如果 module 是 system 或 amd,则所有模块文件也将在所有全局内容之后连接到该文件中。
注意:除非 module 是 None、System 或 AMD,否则不能使用 outFile。此选项不能用于捆绑 CommonJS 或 ES6 模块。
preserveConstEnums
默认值: 如果 isolatedModules 为
true,则为true;否则为false。发布版本: 1.4
不删除生成的代码中的 const enum 声明。const enum 通过输出枚举值而不是引用,提供了一种在运行时减少应用程序整体内存占用的方法。
例如,使用此 TypeScript:
const enum Album {
JimmyEatWorldFutures = 1,
TubRingZooHypothesis = 2,
DogFashionDiscoAdultery = 3,
}
const selectedAlbum = Album.JimmyEatWorldFutures;
if (selectedAlbum === Album.JimmyEatWorldFutures) {
console.log("That is a great choice.");
}Try默认的 const enum 行为是将任何 Album.Something 转换为相应的数字字面量,并从 JavaScript 中完全删除对枚举的引用。
"use strict";
const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;
if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {
console.log("That is a great choice.");
}
Try当 preserveConstEnums 设置为 true 时,enum 在运行时存在,并且数字仍然会输出。
"use strict";
var Album;
(function (Album) {
Album[Album["JimmyEatWorldFutures"] = 1] = "JimmyEatWorldFutures";
Album[Album["TubRingZooHypothesis"] = 2] = "TubRingZooHypothesis";
Album[Album["DogFashionDiscoAdultery"] = 3] = "DogFashionDiscoAdultery";
})(Album || (Album = {}));
const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;
if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {
console.log("That is a great choice.");
}
Try这实际上使此类 const enum 仅成为源代码特性,没有运行时痕迹。
removeComments
- 发布版本: 1.0
在转换为 JavaScript 时,从 TypeScript 文件中去除所有注释。默认为 false。
例如,这是一个带有 JSDoc 注释的 TypeScript 文件:
/** The translation of 'Hello world' into Portuguese */
export const helloWorldPTBR = "Olá Mundo";当 removeComments 设置为 true 时:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.helloWorldPTBR = void 0;
exports.helloWorldPTBR = "Olá Mundo";
Try不设置 removeComments 或将其设为 false 时:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.helloWorldPTBR = void 0;
/** The translation of 'Hello world' into Portuguese */
exports.helloWorldPTBR = "Olá Mundo";
Try这意味着你的注释将显示在 JavaScript 代码中。
sourceMap
- 发布版本: 1.0
启用源映射文件的生成。 这些文件允许调试器和其他工具在实际处理输出的 JavaScript 文件时显示原始的 TypeScript 源代码。 源映射文件作为 .js.map(或 .jsx.map)文件输出,与相应的 .js 输出文件并列。
.js 文件将依次包含一个源映射注释,以向外部工具指示文件的位置,例如:
// helloWorld.ts
export declare const helloWorld = "hi";使用 sourceMap 设置为 true 进行编译会创建以下 JavaScript 文件:
// helloWorld.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.helloWorld = "hi";
//# sourceMappingURL=// helloWorld.js.map并且还会生成此 JSON 映射:
// helloWorld.js.map
{
"version": 3,
"file": "ex.js",
"sourceRoot": "",
"sources": ["../ex.ts"],
"names": [],
"mappings": ";;AAAa,QAAA,UAAU,GAAG,IAAI,CAAA"
}sourceRoot
- 发布版本: 1.0
指定调试器应定位 TypeScript 文件的位置,而不是相对源位置。 此字符串在源映射中会被原样使用,你可以使用路径或 URL:
{
"compilerOptions": {
"sourceMap": true,
"sourceRoot": "https://my-website.com/debug/source/"
}
}将声明 index.js 的源文件位于 https://my-website.com/debug/source/index.ts。
stripInternal 内部
- 发布版本: 1.5
不输出在 JSDoc 注释中带有 @internal 注解的代码的声明。 这是一个内部编译器选项;请自行承担使用风险,因为编译器不检查结果是否有效。 如果你正在寻找一个工具来处理 d.ts 文件中额外的可见性级别,请查看 api-extractor。
/**
* 一周中的天数
* @internal
*/
export const daysInAWeek = 7;
/** 计算某人一周的收入 */
export function weeklySalary(dayRate: number) {
return daysInAWeek * dayRate;
}Try当标志设置为 false(默认)时:
/**
* 一周中的天数
* @internal
*/
export declare const daysInAWeek = 7;
/** 计算某人一周的收入 */
export declare function weeklySalary(dayRate: number): number;
Try当 stripInternal 设置为 true 时,输出的 d.ts 将被编辑。
JavaScript 输出仍然相同。