声明文件生成 - declaration
为项目中的每个 TypeScript 或 JavaScript 文件生成 .d.ts 文件。这些 .d.ts 文件是类型定义文件,用于描述模块的外部 API。通过 .d.ts 文件,TypeScript 等工具可以为未类型化的代码提供智能提示和准确的类型信息。
当 declaration 设置为 true 时,使用以下 TypeScript 代码运行编译器:
export let helloWorld = "hi";将生成如下的 index.js 文件:
export let helloWorld = "hi";同时会生成对应的 helloWorld.d.ts 文件:
export declare let helloWorld: string;当处理 JavaScript 文件的 .d.ts 文件时,你可能需要使用 emitDeclarationOnly 或使用 outDir 来确保 JavaScript 文件不会被覆盖。
默认值:
- 如果设置了 composite 则为 true;否则为 false
相关配置:
- declarationDir
- emitDeclarationOnly
发布版本:1.0
声明文件目录 - declarationDir
提供一种配置声明文件输出根目录的方式。
示例目录结构:
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.ts相关配置:
- declaration
发布版本:2.0
声明文件映射 - declarationMap
为 .d.ts 文件生成源映射文件,这些映射文件可以映射回原始的 .ts 源文件。这将允许像 VS Code 这样的编辑器在使用”转到定义”等功能时跳转到原始的 .ts 文件。
如果你正在使用项目引用(project references),强烈建议启用此选项。
发布版本:2.9
降级迭代 - downlevelIteration
降级(Downleveling)是 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 代码:
const str = "Hello!";
for (const s of str) {
console.log(s);
}在未启用 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);
}这通常是人们所期望的,但它并不是 100% 符合 ECMAScript 迭代协议。某些字符串,如表情符号(😜),的 .length 为 2(甚至更多!),但在 for-of 循环中应该作为 1 个单位进行迭代。
当启用 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.");
};你可以通过 importHelpers 使用 tslib 来减少内联 JavaScript 的数量。
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; }
}注意:如果运行时环境中不存在 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 一样,如果存在 Symbol.iterator,downlevelIteration 将使用它来更准确地模拟 ES6 行为。
相关配置:
- importHelpers
发布版本:2.3
生成 BOM - emitBOM
控制 TypeScript 在写入输出文件时是否会生成字节顺序标记(BOM)。某些运行时环境需要 BOM 来正确解释 JavaScript 文件;而其他环境则要求不能有 BOM。除非你有特殊原因需要更改,否则默认值 false 通常是最佳选择。
发布版本:1.0
仅生成声明文件 - emitDeclarationOnly
只生成 .d.ts 文件,不生成 .js 文件。
这个设置在以下两种情况下很有用:
- 你使用 TypeScript 以外的转译器来生成 JavaScript。
- 你使用 TypeScript 仅为你的使用者生成 d.ts 文件。
相关配置:
- declaration
发布版本:2.8
导入辅助函数 - importHelpers
对于某些降级操作,TypeScript 使用一些辅助代码来处理类的继承、数组或对象的展开以及异步操作。默认情况下,这些辅助函数会被插入到使用它们的文件中。如果在许多不同的模块中使用相同的辅助函数,这可能会导致代码重复。
如果启用 importHelpers 标志,这些辅助函数将从 tslib 模块中导入。你需要确保在运行时可以导入 tslib 模块。这只影响模块;全局脚本文件不会尝试导入模块。
例如,对于这段 TypeScript 代码:
export function fn(arr: number[]) {
const arr2 = [1, ...arr];
}当启用 downlevelIteration 但 importHelpers 为 false 时:
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));
};
export function fn(arr) {
var arr2 = __spreadArray([1], __read(arr), false);
}当同时启用 downlevelIteration 和 importHelpers 时:
import { __read, __spreadArray } from "tslib";
export function fn(arr) {
var arr2 = __spreadArray([1], __read(arr), false);
}当你提供了这些函数的自己的实现时,可以使用 noEmitHelpers。
相关配置:
- noEmitHelpers
- downlevelIteration
发布版本:2.1
内联源映射 - inlineSourceMap
当设置此选项时,TypeScript 不会生成单独的 .js.map 文件来提供源映射,而是将源映射内容直接嵌入到 .js 文件中。虽然这会导致 JS 文件变大,但在某些场景下会很方便。例如,当你需要在不允许服务 .map 文件的网络服务器上调试 JS 文件时。
此选项与 sourceMap 互斥。
例如,对于这段 TypeScript 代码:
const helloWorld = "hi";
console.log(helloWorld);转换为这段 JavaScript 代码:
"use strict";
const helloWorld = "hi";
console.log(helloWorld);当启用 inlineSourceMap 构建时,文件底部会包含一个注释,其中包含了该文件的源映射:
"use strict";
const helloWorld = "hi";
console.log(helloWorld);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ==发布版本:1.5
内联源码 - inlineSources
当设置此选项时,TypeScript 会将原始 .ts 文件的内容作为嵌入字符串包含在源映射中(使用源映射的 sourcesContent 属性)。这通常在与 inlineSourceMap 相同的场景下很有用。
需要设置 sourceMap 或 inlineSourceMap 才能使用此选项。
例如,对于这段 TypeScript 代码:
const helloWorld = "hi";
console.log(helloWorld);默认情况下转换为这段 JavaScript 代码:
"use strict";
const helloWorld = "hi";
console.log(helloWorld);当同时启用 inlineSources 和 inlineSourceMap 构建时,文件底部会包含一个注释,其中包含了该文件的源映射。注意,这里的结尾与 inlineSourceMap 示例中的不同,因为源映射现在还包含了原始源代码:
"use strict";
const helloWorld = "hi";
console.log(helloWorld);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19发布版本:1.5
映射根目录 - mapRoot
指定调试器应该查找映射文件的位置,而不是生成的位置。这个字符串会在源映射中按原样处理,例如:
{
"compilerOptions": {
"sourceMap": true,
"mapRoot": "https://my-website.com/debug/sourcemaps/"
}
}这将声明 index.js 的源映射位于 https://my-website.com/debug/sourcemaps/index.js.map。
发布版本:1.0
换行符 - newLine
指定生成文件时使用的行尾序列:‘CRLF’(dos)或 ‘LF’(unix)。
默认值:
- lf
允许值:
- crlf
- lf
发布版本:1.5
不生成输出 - noEmit
不生成编译器输出文件,如 JavaScript 源代码、源映射或声明文件。
这为其他工具(如 Babel 或 swc)提供了空间,让它们来处理将 TypeScript 文件转换为可以在 JavaScript 环境中运行的文件。
你可以将 TypeScript 用作提供编辑器集成的工具,以及源代码类型检查器。
发布版本:1.5
不生成辅助函数 - noEmitHelpers
不使用 importHelpers 导入辅助函数,而是在全局作用域中提供你所使用的辅助函数的实现,并完全关闭辅助函数的生成。
例如,在 ES5 中使用这个异步函数需要一个类似 await 的函数和类似生成器的函数来运行:
const getAPI = async (url: string) => {
// Get API
return {};
};这会生成相当多的 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) {
// Get API
return [2 /*return*/, {}];
});
}); };通过这个标志,你可以使用自己的全局实现来替换这些辅助函数:
"use strict";
var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
// Get API
return [2 /*return*/, {}];
});
}); };相关配置:
- importHelpers
发布版本:1.5
有错误时不生成输出 - noEmitOnError
如果报告了任何错误,不生成编译器输出文件,如 JavaScript 源代码、源映射或声明文件。
默认值为 false,这使得在类似监视的环境中更容易使用 TypeScript,在这种环境中,你可能希望在确保所有错误都已解决之前,在另一个环境中查看代码更改的结果。
发布版本:1.4
输出目录 - 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.json相关配置:
- out
- outFile
发布版本:1.0
保留常量枚举 - preserveConstEnums
不在生成的代码中擦除 const enum 声明。const enums 通过在编译时将枚举值替换为实际值而不是引用,提供了一种减少应用程序运行时内存占用的方法。
例如,对于这段 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.");
}const enum 的默认行为是将任何 Album.Something 转换为相应的数字字面量,并从 JavaScript 中完全移除对枚举的引用:
"use strict";
const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;
if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {
console.log("That is a great choice.");
}当 preserveConstEnums 设置为 true 时,枚举在运行时依然存在,并且数字值仍然会被生成:
"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.");
}这本质上使得这样的 const enums 仅作为源代码特性存在,在运行时不留下任何痕迹。
默认值:
- 如果设置了 isolatedModules 则为 true;否则为 false
发布版本:1.4
移除注释 - removeComments
在转换为 JavaScript 时从 TypeScript 文件中删除所有注释。默认值为 false。
例如,这是一个带有 JSDoc 注释的 TypeScript 文件:
/** The translation of 'Hello world' into Portuguese */
export const helloWorldPTBR = "Olá Mundo";当 removeComments 设置为 true 时:
export const helloWorldPTBR = "Olá Mundo";当未设置 removeComments 或设置为 false 时:
/** The translation of 'Hello world' into Portuguese */
export const helloWorldPTBR = "Olá Mundo";这意味着你的注释将会出现在 JavaScript 代码中。
发布版本:1.0
源映射 - sourceMap
启用源映射文件的生成。这些文件允许调试器和其他工具在实际处理生成的 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"
}发布版本:1.0
源根目录 - sourceRoot
指定调试器应该在哪里查找 TypeScript 文件,而不是使用相对源位置。这个字符串在源映射中会被按原样处理,你可以使用路径或 URL:
{
"compilerOptions": {
"sourceMap": true,
"sourceRoot": "https://my-website.com/debug/source/"
}
}这将声明 index.js 的源文件位于 https://my-website.com/debug/source/index.ts。
发布版本:1.0
移除内部声明 - stripInternal
不为在其 JSDoc 注释中带有 @internal 注解的代码生成声明。这是一个内部编译器选项;使用时需要自担风险,因为编译器不会检查结果是否有效。如果你正在寻找一个工具来处理 d.ts 文件中的额外可见性级别,请查看 api-extractor。
/**
* Days available in a week
* @internal
*/
export const daysInAWeek = 7;
/** Calculate how much someone earns in a week */
export function weeklySalary(dayRate: number) {
return daysInAWeek * dayRate;
}当标志设置为 false(默认值)时:
/**
* Days available in a week
* @internal
*/
export declare const daysInAWeek = 7;
/** Calculate how much someone earns in a week */
export declare function weeklySalary(dayRate: number): number;当 stripInternal 设置为 true 时,生成的 d.ts 将被编辑:
/** Calculate how much someone earns in a week */
export declare function weeklySalary(dayRate: number): number;JavaScript 输出仍然保持不变。
发布版本:1.5