TSConfig 参考

编译器选项

"compilerOptions"

JavaScript 支持

  1. allowJs,
  2. checkJs and
  3. maxNodeModuleJsDepth

编辑器支持

  1. disableSizeLimit and
  2. plugins

命令行

    根字段

    首先介绍的是 TSConfig 中的根级选项——这些选项与你如何配置 TypeScript 或 JavaScript 项目有关。

    # 文件 - files

    指定要包含到程序中的文件允许列表。只要有文件找不到,就会发生错误。

    {
    "": [
    "core.ts",
    "sys.ts",
    "types.ts",
    "scanner.ts",
    "parser.ts",
    "utilities.ts",
    "binder.ts",
    "checker.ts",
    "tsc.ts"
    ]
    }

    当你只有少量文件、不需要用 glob 来引用大量文件时,这个选项很有用。如果你需要那样做,请使用 include。

    • 默认值:

      false

    • 相关:
      • include

      • exclude

    • 发布于:

      1.5

    # 继承 - extends

    extends 的值是一个字符串,其中包含要继承的另一个配置文件的路径。该路径可以使用 Node.js 风格的解析方式。

    先加载基础文件中的配置,再由继承它的配置文件中的配置覆盖。配置文件中出现的所有相对路径,都会相对于它们原本所在的配置文件来解析。

    需要注意的是,继承配置中的 files、include 和 exclude 会覆盖基础配置文件中的对应项;此外,配置文件之间不允许出现循环引用。

    目前,唯一不参与继承的顶层属性是 references。

    示例

    configs/base.json:

    tsconfig.json:

    {
    "": "./configs/base",
    "": ["main.ts", "supplemental.ts"]
    }

    tsconfig.nostrictnull.json:

    {
    "": "./tsconfig",
    }
    }

    配置文件中带有相对路径、且未被排除在继承之外的属性,会相对于它们原本所在的配置文件来解析。

    • 默认值:

      false

    • 发布于:

      2.1

    # 包含 - include

    指定一个文件名或模式数组,用于包含到程序中。这些文件名会相对于包含 tsconfig.json 文件的目录来解析。

    json
    {
    "include": ["src/**/*", "tests/**/*"]
    }

    这会包含:

    .
    ├── scripts ⨯
    │ ├── lint.ts ⨯
    │ ├── update_deps.ts ⨯
    │ └── utils.ts ⨯
    ├── src ✓
    │ ├── client ✓
    │ │ ├── index.ts ✓
    │ │ └── utils.ts ✓
    │ ├── server ✓
    │ │ └── index.ts ✓
    ├── tests ✓
    │ ├── app.test.ts ✓
    │ ├── utils.ts ✓
    │ └── tests.d.ts ✓
    ├── package.json
    ├── tsconfig.json
    └── yarn.lock

    include 和 exclude 支持使用通配符来构成 glob 模式:

    • * 匹配零个或多个字符(不包括目录分隔符)
    • ? 匹配任意单个字符(不包括目录分隔符)
    • **/ 匹配任意层级的嵌套目录

    如果模式中最后一段路径不包含文件扩展名或通配符,那么它会被视为目录,并包含该目录下具有受支持扩展名的文件(例如默认包含 .ts、.tsx 和 .d.ts;如果 allowJs 设置为 true,则还会包含 .js 和 .jsx)。

    • 默认值:

      如果指定了 files,则为 [];否则为 **/*。

    • 相关:
      • files

      • exclude

    • 发布于:

      2.0

    # 排除 - exclude

    指定一个文件名或模式数组,在解析 include 时应跳过这些文件或模式。

    重要:exclude只会改变因 include 设置而纳入的文件。由 exclude 指定的文件,仍可能因代码中的 import 语句、types 包含项、/// <reference 指令,或被列入 files 列表,而成为代码库的一部分。

    它并不是一种阻止文件进入代码库的机制——它只是改变 include 设置所找到的内容。

    • 默认值:

      node_modules、bower_components、jspm_packages 以及 outDir

    • 相关:
      • include

      • files

    • 发布于:

      2.0

    # 引用 - references

    项目引用是一种将 TypeScript 程序组织成更小片段的方式。使用项目引用可以大幅缩短构建时间和编辑器交互时间,强制组件之间的逻辑分离,并以全新的改进方式组织代码。

    你可以在手册的项目引用章节中进一步了解引用的工作原理

    • 默认值:

      false

    • 发布版本:

      3.0

    编译器选项

    这些选项构成了 TypeScript 配置的主体,涵盖了语言应如何工作的各个方面。

    #类型检查

    # 允许不可达代码 - allowUnreachableCode

    当:

    • undefined(默认)以警告形式向编辑器提供建议
    • true 忽略不可达代码
    • false 对不可达代码引发编译器错误

    这些警告仅针对因使用 JavaScript 语法而可证明不可达的代码,例如:

    ts
    function fn(n: number) {
    if (n > 5) {
    return true;
    } else {
    return false;
    }
    return true;
    }

    使用 "allowUnreachableCode": false:

    ts
    function fn(n: number) {
    if (n > 5) {
    return true;
    } else {
    return false;
    }
    return true;
    Unreachable code detected.7027Unreachable code detected.
    }
    Try

    这不会影响基于类型分析而看起来不可达的代码所产生的错误。

    • 发布版本:

      1.8

    # 允许未使用标签 - allowUnusedLabels

    当:

    • undefined(默认)以警告形式向编辑器提供建议
    • true 忽略未使用的标签
    • false 对未使用的标签引发编译器错误

    标签在 JavaScript 中非常罕见,通常表明有人试图编写对象字面量:

    ts
    function verifyAge(age: number) {
    // Forgot 'return' statement
    if (age > 18) {
    verified: true;
    Unused label.7028Unused label.
    }
    }
    Try
    • 发布版本:

      1.8

    # 始终严格 - alwaysStrict

    确保你的文件以 ECMAScript 严格模式解析,并为每个源文件输出 “use strict”。

    ECMAScript 严格模式在 ES5 中引入,它对 JavaScript 引擎的运行时行为做了一些调整以提升性能,并使一组错误抛出异常而不是被静默忽略。

    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      2.1

    # 精确可选属性类型 - exactOptionalPropertyTypes

    启用 exactOptionalPropertyTypes 后,TypeScript 会对如何处理 type 或 interfaces 中带 ? 前缀的属性应用更严格的规则。

    例如,这个接口声明了一个属性,它可以是两个字符串之一:‘dark’ 或 ‘light’,或者根本不应存在于对象中。

    ts
    interface UserDefaults {
    // The absence of a value represents 'system'
    colorThemeOverride?: "dark" | "light";
    }

    在未启用此标志时,你可以将 colorThemeOverride 设为三个值:“dark”、“light” 和 undefined。

    将值设为 undefined 会使大多数 JavaScript 运行时的存在性检查失败,这在效果上相当于假值。然而,这并不完全准确;colorThemeOverride: undefined 与未定义 colorThemeOverride 并不相同。例如,在键为 undefined 与键未定义这两种情况下,"colorThemeOverride" in settings 的行为会有所不同。

    exactOptionalPropertyTypes 使 TypeScript 真正强制执行作为可选属性提供的定义:

    ts
    const settings = getUserSettings();
    settings.colorThemeOverride = "dark";
    settings.colorThemeOverride = "light";
     
    // But not:
    settings.colorThemeOverride = undefined;
    Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.2412Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.
    Try
    • 推荐
    • 发布版本:

      4.4

    # Switch 中禁止贯穿 - noFallthroughCasesInSwitch

    对 switch 语句中的贯穿情况报告错误。确保 switch 语句中任何非空 case 都包含 break、return 或 throw。这意味着你不会意外发布 case 贯穿的 bug。

    ts
    const a: number = 6;
     
    switch (a) {
    case 0:
    Fallthrough case in switch.7029Fallthrough case in switch.
    console.log("even");
    case 1:
    console.log("odd");
    break;
    }
    Try
    • 发布版本:

      1.8

    # 禁止隐式 Any - noImplicitAny

    在某些没有类型注解的情况下,当 TypeScript 无法推断类型时,会退而将变量设为 any 类型。

    这可能导致一些错误被漏掉,例如:

    ts
    function fn(s) {
    // No error?
    console.log(s.subtr(3));
    }
    fn(42);
    Try

    然而,开启 noImplicitAny 后,只要 TypeScript 本会推断为 any,就会报错:

    ts
    function fn(s) {
    Parameter 's' implicitly has an 'any' type.7006Parameter 's' implicitly has an 'any' type.
    console.log(s.subtr(3));
    }
    Try
    • 推荐
    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      1.0

    # 禁止隐式 override - noImplicitOverride

    在使用继承的类时,如果基类中的函数被重命名,子类可能会与它重写的函数“失去同步”。

    例如,假设你在为一个音乐专辑同步系统建模:

    ts
    class Album {
    download() {
    // Default behavior
    }
    }
     
    class SharedAlbum extends Album {
    download() {
    // Override to get info from many sources
    }
    }
    Try

    后来,当你添加对机器学习生成播放列表的支持时,你把 Album 类重构为具有一个 ‘setup’ 函数:

    ts
    class Album {
    setup() {
    // Default behavior
    }
    }
     
    class MLAlbum extends Album {
    setup() {
    // Override to get info from algorithm
    }
    }
     
    class SharedAlbum extends Album {
    download() {
    // Override to get info from many sources
    }
    }
    Try

    在这种情况下,TypeScript 没有发出任何警告,提示 SharedAlbum 上的 download 本应重写基类中的某个函数。

    使用 noImplicitOverride,你可以通过确保重写函数包含 override 关键字,保证子类永远不会失去同步。

    以下示例启用了 noImplicitOverride,你可以看到缺少 override 时收到的错误:

    ts
    class Album {
    setup() {}
    }
     
    class MLAlbum extends Album {
    override setup() {}
    }
     
    class SharedAlbum extends Album {
    setup() {}
    This member must have an 'override' modifier because it overrides a member in the base class 'Album'.4114This member must have an 'override' modifier because it overrides a member in the base class 'Album'.
    }
    Try
    • 发布版本:

      4.3

    # 禁止隐式返回 - noImplicitReturns

    启用后,TypeScript 会检查函数中的所有代码路径,确保它们都返回一个值。

    ts
    function lookupHeadphonesManufacturer(color: "blue" | "black"): string {
    Function lacks ending return statement and return type does not include 'undefined'.2366Function lacks ending return statement and return type does not include 'undefined'.
    if (color === "blue") {
    return "beats";
    } else {
    ("bose");
    }
    }
    Try
    • 发布版本:

      1.8

    # 禁止隐式 this - noImplicitThis

    对隐含“any”类型的“this”表达式报错。

    例如,下面的类返回一个函数,该函数试图访问 this.width 和 this.height——但 getAreaFunction 内部那个函数中的 this 上下文并不是 Rectangle 的实例。

    ts
    class Rectangle {
    width: number;
    height: number;
     
    constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
    }
     
    getAreaFunction() {
    return function () {
    return this.width * this.height;
    'this' implicitly has type 'any' because it does not have a type annotation.
    'this' implicitly has type 'any' because it does not have a type annotation.
    2683
    2683
    'this' implicitly has type 'any' because it does not have a type annotation.
    'this' implicitly has type 'any' because it does not have a type annotation.
    };
    }
    }
    Try
    • 推荐
    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      2.0

    # 禁止从索引签名访问属性 - noPropertyAccessFromIndexSignature

    此设置确保通过“点”(obj.key)语法和“索引”(obj["key"])语法访问字段的方式,与属性在类型中的声明方式保持一致。

    没有此标志时,TypeScript 会允许你使用点语法访问未定义的字段:

    ts
    interface GameSettings {
    // Known up-front properties
    speed: "fast" | "medium" | "slow";
    quality: "high" | "low";
     
    // Assume anything unknown to the interface
    // is a string.
    [key: string]: string;
    }
     
    const settings = getSettings();
    settings.speed;
    (property) GameSettings.speed: "fast" | "medium" | "slow"
    settings.quality;
    (property) GameSettings.quality: "high" | "low"
     
    // Unknown key accessors are allowed on
    // this object, and are `string`
    settings.username;
    (index) GameSettings[string]: string
    Try

    开启此标志后会报错,因为这个未知字段使用了点语法而不是索引语法。

    ts
    const settings = getSettings();
    settings.speed;
    settings.quality;
     
    // This would need to be settings["username"];
    settings.username;
    Property 'username' comes from an index signature, so it must be accessed with ['username'].4111Property 'username' comes from an index signature, so it must be accessed with ['username'].
    (index) GameSettings[string]: string
    Try

    此标志的目的在于让你在调用语法中表明意图:你对这个属性存在有多确定。

    • 发布版本:

      4.2

    # 禁止未检查的索引访问 - noUncheckedIndexedAccess

    TypeScript 可以通过索引签名来描述那些键未知但值已知的对象。

    ts
    interface EnvironmentVars {
    NAME: string;
    OS: string;
     
    // Unknown properties are covered by this index signature.
    [propName: string]: string;
    }
     
    declare const env: EnvironmentVars;
     
    // Declared as existing
    const sysName = env.NAME;
    const os = env.OS;
    const os: string
     
    // Not declared, but because of the index
    // signature, then it is considered a string
    const nodeEnv = env.NODE_ENV;
    const nodeEnv: string
    Try

    开启 noUncheckedIndexedAccess 后,类型中任何未声明的字段都会加上 undefined。

    ts
    declare const env: EnvironmentVars;
     
    // Declared as existing
    const sysName = env.NAME;
    const os = env.OS;
    const os: string
     
    // Not declared, but because of the index
    // signature, then it is considered a string
    const nodeEnv = env.NODE_ENV;
    const nodeEnv: string | undefined
    Try
    • 发布版本:

      4.1

    # 禁止未使用的局部变量 - noUnusedLocals

    对未使用的局部变量报告错误。

    ts
    const createKeyboard = (modelID: number) => {
    const defaultModelID = 23;
    'defaultModelID' is declared but its value is never read.6133'defaultModelID' is declared but its value is never read.
    return { type: "keyboard", modelID };
    };
    Try
    • 发布版本:

      2.0

    # 禁止未使用的参数 - noUnusedParameters

    对函数中未使用的参数报告错误。

    ts
    const createDefaultKeyboard = (modelID: number) => {
    'modelID' is declared but its value is never read.6133'modelID' is declared but its value is never read.
    const defaultModelID = 23;
    return { type: "keyboard", modelID: defaultModelID };
    };
    Try

    名称以下划线(_)开头的参数声明不受未使用参数检查的约束,例如:

    ts
    const createDefaultKeyboard = (_modelID: number) => {
    return { type: "keyboard" };
    };
    Try
    • 发布版本:

      2.0

    # 严格模式 - strict

    strict 标志会启用一系列类型检查行为,从而更有力地保证程序的正确性。开启它等同于启用下面列出的所有严格模式家族选项。之后你可以按需关闭其中个别的严格模式家族检查。

    未来版本的 TypeScript 可能会在该标志下引入额外的更严格检查,因此升级 TypeScript 可能会在你的程序中产生新的类型错误。在适当且可行的情况下,会添加相应的标志来禁用该行为。

    • 推荐
    • 默认值:

      true

    • 相关:
      • alwaysStrict

      • strictNullChecks

      • strictBindCallApply

      • strictBuiltinIteratorReturn

      • strictFunctionTypes

      • strictPropertyInitialization

      • noImplicitAny

      • noImplicitThis

      • useUnknownInCatchVariables

    • 发布版本:

      2.3

    # 严格的 bind/call/apply - strictBindCallApply

    设置后,TypeScript 会检查函数的 call、bind 和 apply 这些内置方法是否以正确的实参调用底层函数:

    ts
    // With strictBindCallApply on
    function fn(x: string) {
    return parseInt(x);
    }
     
    const n1 = fn.call(undefined, "10");
     
    const n2 = fn.call(undefined, false);
    Argument of type 'boolean' is not assignable to parameter of type 'string'.2345Argument of type 'boolean' is not assignable to parameter of type 'string'.
    Try

    否则,这些函数会接受任意实参,并返回 any:

    ts
    // With strictBindCallApply off
    function fn(x: string) {
    return parseInt(x);
    }
     
    // Note: No error; return type is 'any'
    const n = fn.call(undefined, false);
    Try
    • 推荐
    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      3.2

    # 严格的迭代器返回值 - strictBuiltinIteratorReturn

    内置迭代器实例化时,其 `TReturn` 类型为 undefined,而不是 `any`。
    • 推荐
    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      5.6

    # 严格的函数类型 - strictFunctionTypes

    启用后,此标志会让函数参数得到更正确的检查。

    下面是一个关闭 strictFunctionTypes 的基本示例:

    ts
    function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
     
    type StringOrNumberFunc = (ns: string | number) => void;
     
    // Unsafe assignment
    let func: StringOrNumberFunc = fn;
    // Unsafe call - will crash
    func(10);
    Try

    当开启 strictFunctionTypes 时,错误会被正确检测到:

    ts
    function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
     
    type StringOrNumberFunc = (ns: string | number) => void;
     
    // Unsafe assignment is prevented
    let func: StringOrNumberFunc = fn;
    Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'. Types of parameters 'x' and 'ns' are incompatible. Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'.2322Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'. Types of parameters 'x' and 'ns' are incompatible. Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'.
    Try

    在开发此功能期间,我们发现了大量本质上不安全的类层次结构,其中一些就存在于 DOM 中。因此,该设置只适用于以函数语法编写的函数,而不适用于以方法语法编写的函数:

    ts
    type Methodish = {
    func(x: string | number): void;
    };
     
    function fn(x: string) {
    console.log("Hello, " + x.toLowerCase());
    }
     
    // Ultimately an unsafe assignment, but not detected
    const m: Methodish = {
    func: fn,
    };
    m.func(10);
    Try
    • 推荐
    • 默认值:

      如果启用 strict 则为 true;否则为 false。

    • 相关:
      • strict

    • 发布版本:

      2.6

    # 严格的空值检查 - strictNullChecks

    当 strictNullChecks 为 false 时,该语言实际上会忽略 null 和 undefined。这可能导致运行时出现意外的错误。

    当 strictNullChecks 为 true 时,null 和 undefined 各自拥有独立的类型,如果你试图在期望具体值的地方使用它们,就会得到类型错误。

    例如,在这段 TypeScript 代码中,users.find 并不保证一定能找到用户,但你可以像它肯定能找到那样编写代码:

    ts
    declare const loggedInUsername: string;
     
    const users = [
    { name: "Oby", age: 12 },
    { name: "Heera", age: 32 },
    ];
     
    const loggedInUser = users.find((u) => u.name === loggedInUsername);
    console.log(loggedInUser.age);
    Try

    将 strictNullChecks 设为 true 后,如果你未保证 loggedInUser 存在就尝试使用它,就会报错。

    ts
    declare const loggedInUsername: string;
     
    const users = [
    { name: "Oby", age: 12 },
    { name: "Heera", age: 32 },
    ];
     
    const loggedInUser = users.find((u) => u.name === loggedInUsername);
    console.log(loggedInUser.age);
    'loggedInUser' is possibly 'undefined'.18048'loggedInUser' is possibly 'undefined'.
    Try

    第二个示例失败,是因为数组的 find 函数大致类似于下面这个简化版本:

    ts
    // When strictNullChecks: true
    type Array = {
    find(predicate: (value: any, index: number) => boolean): S | undefined;
    };
    // When strictNullChecks: false the undefined is removed from the type system,
    // allowing you to write code which assumes it always found a result
    type Array = {
    find(predicate: (value: any, index: number) => boolean): S;
    };
    • 推荐
    • 默认值:

      true,前提是启用 strict;否则为 false。

    • 相关:
      • strict

    • 发布于:

      2.0

    # 严格的属性初始化 - strictPropertyInitialization

    当设为 true 时,若类属性已声明但未在构造函数中赋值,TypeScript 将报错。

    ts
    class UserAccount {
    name: string;
    accountType = "user";
     
    email: string;
    Property 'email' has no initializer and is not definitely assigned in the constructor.2564Property 'email' has no initializer and is not definitely assigned in the constructor.
    address: string | undefined;
     
    constructor(name: string) {
    this.name = name;
    // Note that this.email is not set
    }
    }
    Try

    在上述情况中:

    • this.name 被显式赋值。
    • this.accountType 有默认值。
    • this.email 未被赋值,会报错。
    • this.address 被声明为可能为 undefined,这意味着它不必被赋值。
    • 推荐
    • 默认值:

      true,前提是启用 strict;否则为 false。

    • 相关:
      • strict

    • 发布于:

      2.7

    # 在 catch 变量中使用 unknown - useUnknownInCatchVariables

    在 TypeScript 4.0 中,添加了支持,允许将 catch 子句中变量的类型从 any 改为 unknown。从而允许这样的代码:

    ts
    try {
    // ...
    } catch (err: unknown) {
    // We have to verify err is an
    // error before using it as one.
    if (err instanceof Error) {
    console.log(err.message);
    }
    }
    Try

    这种模式确保错误处理代码更加全面,因为你无法预先保证被抛出的对象确实是 Error 的子类。启用 useUnknownInCatchVariables 标志后,你既不需要额外的语法(: unknown),也不需要 lint 规则来强制这一行为。

    • 推荐
    • 默认值:

      true,前提是启用 strict;否则为 false。

    • 相关:
      • strict

    • 发布于:

      4.4

    #模块

    # 允许任意扩展名 - allowArbitraryExtensions

    在 TypeScript 5.0 中,当导入路径以不是已知 JavaScript 或 TypeScript 文件扩展名的扩展名结尾时,编译器会以 {file basename}.d.{extension}.ts 的形式查找该路径的声明文件。例如,如果你在打包器项目中使用 CSS 加载器,你可能想为这些样式表编写(或生成)声明文件:

    css
    /* app.css */
    .cookie-banner {
    display: none;
    }
    ts
    // app.d.css.ts
    declare const css: {
    cookieBanner: string;
    };
    export default css;
    ts
    // App.tsx
    import styles from "./app.css";
    styles.cookieBanner; // string

    默认情况下,这个导入会报错,提示 TypeScript 不理解这种文件类型,而且你的运行时可能不支持导入它。但如果你已经配置好运行时或打包器来处理它,就可以用新的 --allowArbitraryExtensions 编译器选项抑制该错误。

    请注意,从历史上看,通常可以通过添加名为 app.css.d.ts 而不是 app.d.css.ts 的声明文件来达到类似效果——不过这仅仅是借助了 Node 针对 CommonJS 的 require 解析规则。严格来说,前者被解释为名为 app.css.js 的 JavaScript 文件的声明文件。由于 Node 的 ESM 支持要求相对文件导入包含扩展名,在 --moduleResolution node16 或 nodenext 下的 ESM 文件中,TypeScript 会对我们的示例写法报错。

    更多信息,请阅读此功能的提案及其对应的 pull request。

    • 发布于:

      5.0

    # 允许导入 TS 扩展名 - allowImportingTsExtensions

    --allowImportingTsExtensions 允许 TypeScript 文件使用 TypeScript 特有的扩展名(如 .ts、.mts 或 .tsx)相互导入。

    此标志仅在启用 --noEmit 或 --emitDeclarationOnly 时允许使用,因为这些导入路径在输出的 JavaScript 文件中无法在运行时解析。这里的预期是你的解析器(例如打包器、运行时或其他工具)会让这些 .ts 文件之间的导入正常工作。

    # 允许 UMD 全局访问 - allowUmdGlobalAccess

    当设为 true 时,allowUmdGlobalAccess 让你可以在模块文件内部以全局变量的方式访问 UMD 导出。模块文件是包含导入和/或导出的文件。没有此标志时,使用 UMD 模块的导出需要一条导入声明。

    此标志的一个示例用例是 Web 项目:你知道某个特定库(如 jQuery 或 Lodash)在运行时始终可用,但无法通过 import 访问它。

    • 发布于:

      3.5

    # 基 URL - baseUrl

    设置一个基目录,用于解析裸模块说明符名称。例如,在如下目录结构中:

    project
    ├── ex.ts
    ├── hello
    │ └── world.ts
    └── tsconfig.json

    设置 "baseUrl": "./" 后,TypeScript 会从与 tsconfig.json 相同的文件夹开始查找文件:

    ts
    import { helloWorld } from "hello/world";
    console.log(helloWorld);

    这种解析的优先级高于从 node_modules 的查找。

    此功能是为在浏览器中配合 AMD 模块加载器使用而设计的,不建议在其他任何上下文中使用。从 TypeScript 4.1 起,使用 paths 时不再需要设置 baseUrl。

    • 发布于:

      2.0

    # 自定义条件 - customConditions

    --customConditions 接受一组额外的条件,当 TypeScript 从 package.json 的 exports 或 imports 字段进行解析时,这些条件应当匹配成功。这些条件会附加到解析器默认使用的既有条件之上。

    例如,在 tsconfig.json 中这样设置该字段:

    jsonc
    {
    "compilerOptions": {
    "target": "es2022",
    "moduleResolution": "bundler",
    "customConditions": ["my-condition"]
    }
    }

    每当 package.json 中引用 exports 或 imports 字段时,TypeScript 都会考虑名为 my-condition 的条件。

    因此,当从具有以下 package.json 的包中导入时

    jsonc
    {
    // ...
    "exports": {
    ".": {
    "my-condition": "./foo.mjs",
    "node": "./bar.mjs",
    "import": "./baz.mjs",
    "require": "./biz.mjs"
    }
    }
    }

    TypeScript 会尝试查找与 foo.mjs 对应的文件。

    该字段仅在 --moduleResolution 的 node16、nodenext 和 bundler 选项下有效。

    • 相关:
      • moduleResolution

      • resolvePackageJsonExports

      • resolvePackageJsonImports

    • 发布于:

      5.0

    # 模块 - module

    设置程序的模块系统。更多信息请参见 TypeScript module 选项背后的理论与其参考页面。对于现代 Node.js 项目,你很可能需要 "nodenext";对于将被打包的代码,则需要 preserve 或 esnext。

    更改 module 会影响 moduleResolution,后者同样有参考页面。

    下面是该文件的一些示例输出:

    ts
    // @filename: index.ts
    import { valueOfPi } from "./constants";
     
    export const twoPi = valueOfPi * 2;
    Try

    CommonJS

    ts
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_1 = require("./constants");
    exports.twoPi = constants_1.valueOfPi * 2;
     
    Try

    UMD

    ts
    (function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
    var v = factory(require, exports);
    if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
    define(["require", "exports", "./constants"], factory);
    }
    })(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_1 = require("./constants");
    exports.twoPi = constants_1.valueOfPi * 2;
    });
     
    Try

    AMD

    ts
    define(["require", "exports", "./constants"], function (require, exports, constants_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    exports.twoPi = constants_1.valueOfPi * 2;
    });
     
    Try

    System

    ts
    System.register(["./constants"], function (exports_1, context_1) {
    "use strict";
    var constants_1, twoPi;
    var __moduleName = context_1 && context_1.id;
    return {
    setters: [
    function (constants_1_1) {
    constants_1 = constants_1_1;
    }
    ],
    execute: function () {
    exports_1("twoPi", twoPi = constants_1.valueOfPi * 2);
    }
    };
    });
     
    Try

    ESNext

    ts
    import { valueOfPi } from "./constants";
    export const twoPi = valueOfPi * 2;
     
    Try

    ES2015/ES6/ES2020/ES2022

    ts
    import { valueOfPi } from "./constants";
    export const twoPi = valueOfPi * 2;
     
    Try

    除 ES2015/ES6 的基础功能外,ES2020 增加了对动态 import和 import.meta 的支持,而 ES2022 进一步增加了对顶层 await 的支持。

    node16/node18/node20/nodenext

    node16、node18、node20 和 nodenext 模式与 Node 的原生 ECMAScript 模块支持集成。输出的 JavaScript 会根据文件扩展名以及最近的 package.json 中 type 设置的值,输出 CommonJS 或 ES2020。模块解析的工作方式也有所不同。你可以在手册和模块参考中了解更多。

    • node16 从 TypeScript 4.7 起可用
    • node18 从 TypeScript 5.8 起可用,作为 node16 的替代,并新增了对导入属性的支持。
    • node20 新增了对 require(ESM) 的支持。
    • nodenext 从 TypeScript 4.7 起可用,但其行为会随 Node.js 的最新稳定版本而变化。--module nodenext 会隐含浮动的 --target esnext。

    preserve

    在 --module preserve 下(TypeScript 5.4 新增),输入文件中书写的 ECMAScript 导入和导出会保留在输出中,而 CommonJS 风格的 import x = require("...") 与 export = ... 语句则输出为 CommonJS 的 require 和 module.exports。换句话说,每个导入或导出语句各自的形式都会被保留,而不会被强制统一为整个编译(甚至整个文件)的单一格式。

    ts
    import { valueOfPi } from "./constants";
    const constants = require("./constants");
    export const piSquared = valueOfPi * constants.valueOfPi;
     
    Try

    虽然在同一个文件中混用 import 与 require 调用很少见,但这种 module 模式最能反映大多数现代打包工具以及 Bun 运行时的能力。

    为什么在使用打包工具或 Bun 时(此时你很可能也设置了 noEmit)仍要关心 TypeScript 的 module 输出?TypeScript 的类型检查和模块解析行为会受到它将要输出的模块格式的影响。设置 module 能让 TypeScript 了解你的打包工具或运行时会如何处理导入与导出,从而确保你在导入值上看到的类型能准确反映运行时或打包之后的实际情况。

    None

    ts
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_1 = require("./constants");
    exports.twoPi = constants_1.valueOfPi * 2;
     
    Try
    • 默认值:

      如果 target 为 ES5,则为 CommonJS;否则为 ES6/ES2015。

    • 允许值:
      • none

      • commonjs

      • amd

      • umd

      • system

      • es6/es2015

      • es2020

      • es2022

      • esnext

      • node16

      • node18

      • node20

      • nodenext

      • preserve

    • 相关:
      • moduleResolution

      • esModuleInterop

      • allowImportingTsExtensions

      • allowArbitraryExtensions

      • resolveJsonModule

    • 发布于:

      1.0

    # 模块解析 - moduleResolution

    指定模块解析策略:

    • 对现代版本的 Node.js,使用 'node16' 或 'nodenext'。Node.js v12 及更高版本同时支持 ECMAScript 导入和 CommonJS require,二者采用不同的算法解析。这些 moduleResolution 值与相应的 module 值组合使用时,会根据 Node.js 在输出的 JavaScript 代码中看到的是 import 还是 require,为每次解析挑选正确的算法。
    • 对 v10 之前的 Node.js 版本,使用 'node10'(以前称为 'node'),这些版本仅支持 CommonJS require。在现代代码中你大概不需要使用 node10。
    • 'bundler' 供打包工具使用。与 node16 和 nodenext 一样,该模式支持 package.json 的 "imports" 和 "exports",但与 Node.js 的解析模式不同,bundler 从不要求导入中的相对路径带文件扩展名。
    • 'classic' 在 1.6 发布之前曾用于 TypeScript。不应再使用 classic。

    有参考页面介绍了TypeScript 模块解析背后的理论以及每个选项的细节。

    • 默认值:

      Node10(如果 module 为 CommonJS);Node16(如果 module 为 Node16、Node18 或 Node20);NodeNext(如果 module 为 NodeNext);Bundler(如果 module 为 Preserve);其他情况下为 Classic。

    • 允许值:
      • classic

      • node10/node

      • node16

      • nodenext

      • bundler

    • 相关:
      • module

      • paths

      • baseUrl

      • rootDirs

      • moduleSuffixes

      • customConditions

      • resolvePackageJsonExports

      • resolvePackageJsonImports

    • 发布版本:

      1.6

    # 模块后缀 - moduleSuffixes

    提供一种方式,用于覆盖解析模块时搜索的默认文件名后缀列表。

    {
    "": [".ios", ".native", ""]
    }
    }

    给定上面的配置,像下面这样的导入:

    ts
    import * as foo from "./foo";

    TypeScript 将依次查找相对文件 ./foo.ios.ts、./foo.native.ts,最后是 ./foo.ts。

    注意 moduleSuffixes 中的空字符串 "",它是 TypeScript 同时查找 ./foo.ts 所必需的。

    此特性对 React Native 项目很有用,其中每个目标平台都可以使用带有不同 moduleSuffixes 的独立 tsconfig.json。

    • 发布版本:

      4.7

    # 不解析 - noResolve

    默认情况下,TypeScript 会检查初始文件集中的 import 和 <reference 指令,并将这些解析出的文件添加到程序中。

    如果设置了 noResolve,则不会执行此过程。不过,import 语句仍会被检查是否能解析到有效模块,因此你需要通过其他方式确保这一点。

    • 发布版本:

      1.0

    # 不检查副作用导入 - noUncheckedSideEffectImports

    在 JavaScript 中,可以 import 一个模块,而不实际从中导入任何值。

    ts
    import "some-module";

    这类导入通常被称为副作用导入,因为它们唯一有用的行为就是执行某种副作用(例如注册全局变量,或为原型添加 polyfill)。

    默认情况下,TypeScript 不会检查这些导入是否有效。如果导入解析到有效的源文件,TypeScript 会加载并检查该文件。如果找不到源文件,TypeScript 会静默忽略该导入。

    这是一种令人意外的行为,但它部分源于对 JavaScript 生态中模式的建模。例如,这种语法也被打包器中的特殊加载器用来加载 CSS 或其他资源。你的打包器可能配置为可以通过编写类似下面的内容来包含特定的 .css 文件:

    tsx
    import "./button-component.css";
    export function Button() {
    // ...
    }

    不过,这会掩盖副作用导入中潜在的拼写错误。

    启用 --noUncheckedSideEffectImports 后,如果 TypeScript 找不到副作用导入对应的源文件,就会报错。

    ts
    import "oops-this-module-does-not-exist";
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // error: Cannot find module 'oops-this-module-does-not-exist' or its corresponding
    // type declarations.

    启用此选项后,一些原本能正常工作的代码可能会报错,比如上面的 CSS 示例。要绕过这一点,只想为资源编写副作用 import 的用户最好编写所谓的带通配符说明符的环境模块声明。它会放在全局文件中,看起来类似下面这样:

    ts
    // ./src/globals.d.ts
    // Recognize all CSS files as module imports.
    declare module "*.css" {}

    事实上,你的项目中可能已经有这样的文件了!例如,运行 vite init 之类的东西可能会创建类似的 vite-env.d.ts。

    • 默认值:

      true

    • 发布版本:

      5.6

    # 路径 - paths

    一系列条目,用于将导入重新映射到查找位置:如果设置了 baseUrl,则相对于它;否则相对于 tsconfig 文件本身。关于 paths 的更详细内容见moduleResolution 参考页面。

    paths 让你声明 TypeScript 应如何解析 require/import 中的导入。

    {
    "": {
    "jquery": ["./vendor/jquery/dist/jquery"]
    }
    }
    }

    这让你可以编写 import "jquery",并在本地获得所有正确的类型。

    {
    "": {
    "app/*": ["./src/app/*"],
    "config/*": ["./src/app/_config/*"],
    "environment/*": ["./src/environments/*"],
    "shared/*": ["./src/app/_shared/*"],
    "helpers/*": ["./src/helpers/*"],
    "tests/*": ["./src/tests/*"]
    }
    }
    }

    在这种情况下,你可以告诉 TypeScript 文件解析器支持若干自定义前缀来查找代码。

    注意,此特性不会改变 tsc 输出导入路径的方式,因此 paths 只应用于告知 TypeScript:另一个工具具有此映射,并会在运行时或打包时使用它。

    • 发布版本:

      2.0

    # 解析 JSON 模块 - resolveJsonModule

    允许导入带 .json 扩展名的模块,这在 Node 项目中很常见。这包括根据静态 JSON 结构为 import 生成类型。

    TypeScript 默认不支持解析 JSON 文件:

    ts
    // @filename: settings.json
    {
    "repo": "TypeScript",
    "dry": false,
    "debug": false
    }
    // @filename: index.ts
    import settings from "./settings.json";
    Cannot find module './settings.json' or its corresponding type declarations.2307Cannot find module './settings.json' or its corresponding type declarations.
     
    settings.debug === true;
    settings.dry === 2;
    Try

    启用该选项后,就可以导入 JSON,并校验该 JSON 文件中的类型。

    ts
    // @filename: settings.json
    {
    "repo": "TypeScript",
    "dry": false,
    "debug": false
    }
    // @filename: index.ts
    import settings from "./settings.json";
     
    settings.debug === true;
    settings.dry === 2;
    This comparison appears to be unintentional because the types 'boolean' and 'number' have no overlap.2367This comparison appears to be unintentional because the types 'boolean' and 'number' have no overlap.
    Try
    • 发布版本:

      2.9

    # 解析 package.json 导出 - resolvePackageJsonExports

    --resolvePackageJsonExports 强制 TypeScript 在由于 node_modules 中的包而读取文件时,查阅 package.json 文件的 exports 字段。

    在 --moduleResolution 的 node16、nodenext 和 bundler 选项下,此选项默认为 true。

    • 默认值:

      当 moduleResolution 为 node16、nodenext 或 bundler 时为 true;否则为 false

    • 相关:
      • moduleResolution

      • customConditions

      • resolvePackageJsonImports

    • 发布版本:

      5.0

    # 解析 package.json 导入 - resolvePackageJsonImports

    当从祖先目录中包含 package.json 的文件发起以 # 开头的查找时,--resolvePackageJsonImports 会强制 TypeScript 查询 package.json 文件的 imports 字段。

    当 --moduleResolution 为 node16、nodenext 或 bundler 时,此选项默认为 true。

    • 默认值:

      当 moduleResolution 为 node16、nodenext 或 bundler 时为 true;否则为 false

    • 相关:
      • moduleResolution

      • customConditions

      • resolvePackageJsonExports

    • 发布版本:

      5.0

    # 重写相对导入扩展名 - rewriteRelativeImportExtensions

    将相对导入路径中的 .ts、.tsx、.mts 和 .cts 文件扩展名改写为输出文件中对应的 JavaScript 扩展名。

    更多信息请参阅 TypeScript 5.7 发行说明。

    • 发布版本:

      5.7

    # 根目录 - rootDir

    默认值:所有非声明输入文件的最长公共路径。如果设置了 composite,则默认值改为包含 tsconfig.json 文件的目录。

    TypeScript 编译文件时,会在输出目录中保持与输入目录相同的目录结构。

    例如,假设你有一些输入文件:

    MyProj
    ├── tsconfig.json
    ├── core
    │ ├── a.ts
    │ ├── b.ts
    │ ├── sub
    │ │ ├── c.ts
    ├── types.d.ts

    推断出的 rootDir 值为所有非声明输入文件的最长公共路径,在这里是 core/。

    如果你的 outDir 为 dist,TypeScript 将写入以下目录树:

    MyProj
    ├── dist
    │ ├── a.js
    │ ├── b.js
    │ ├── sub
    │ │ ├── c.js

    不过,你可能希望 core 也成为输出目录结构的一部分。通过在 tsconfig.json 中设置 rootDir: ".",TypeScript 将写入以下目录树:

    MyProj
    ├── dist
    │ ├── core
    │ │ ├── a.js
    │ │ ├── b.js
    │ │ ├── sub
    │ │ │ ├── c.js

    重要的是,rootDir 不会影响哪些文件成为编译的一部分。它与 include、exclude 或 files 这些 tsconfig.json 设置没有交互。

    请注意,TypeScript 绝不会把输出文件写到 outDir 之外的目录,也绝不会跳过生成任何文件。因此,rootDir 还强制要求所有需要生成的文件都位于 rootDir 路径之下。

    例如,假设你有以下目录树:

    MyProj
    ├── tsconfig.json
    ├── core
    │ ├── a.ts
    │ ├── b.ts
    ├── helpers.ts

    如果把 rootDir 指定为 core并且把 include 指定为 * 就会报错,因为这会创建一个需要生成到 outDir 之外的文件(helpers.ts),即 ../helpers.js。

    • 默认值:

      根据输入文件列表计算得出。

    • 发布版本:

      1.5

    # 根目录组 - rootDirs

    使用 rootDirs,你可以告知编译器存在多个充当单一根的“虚拟”目录。这样,编译器就能在这些“虚拟”目录内解析相对模块导入,就好像它们被合并成了一个目录。

    例如:

    src
    └── views
    └── view1.ts (can import "./template1", "./view2`)
    └── view2.ts (can import "./template1", "./view1`)
    generated
    └── templates
    └── views
    └── template1.ts (can import "./view1", "./view2")
    {
    "": ["src/views", "generated/templates/views"]
    }
    }

    这不会影响 TypeScript 如何生成 JavaScript,它只是模拟了一种假设:这些相对路径在运行时能够正常工作。

    rootDirs 可用于为不是 TypeScript 或 JavaScript 的文件提供单独的“类型层”,方法是在另一个文件夹中为生成的 .d.ts 文件提供一个存放位置。对于打包应用来说,这种技术很有用——在这类应用中,你会 import 一些不一定是代码的文件:

    sh
    src
    └── index.ts
    └── css
    └── main.css
    └── navigation.css
    generated
    └── css
    └── main.css.d.ts
    └── navigation.css.d.ts
    {
    "": ["src", "generated"]
    }
    }

    这种技术让你可以提前为非代码源文件生成类型。导入随后会基于源文件的位置自然工作。例如 ./src/index.ts 可以导入文件 ./src/css/main.css,TypeScript 会通过相应生成的声明文件了解打包器对该文件类型的行为。

    ts
    // @filename: index.ts
    import { appClass } from "./main.css";
    Try
    • 默认值:

      根据输入文件列表计算得出。

    • 发布版本:

      2.0

    # 类型根目录 - typeRoots

    默认情况下,所有可见的“@types”包都会被包含进编译中。任何外层文件夹的 node_modules/@types 中的包都被视为可见。例如,这意味着 ./node_modules/@types/、../node_modules/@types/、../../node_modules/@types/ 等目录中的包都可见。

    如果指定了 typeRoots,则只包含 typeRoots 下的包。例如:

    {
    "": ["./typings", "./vendor/types"]
    }
    }

    这个配置文件将包含 ./typings 和 ./vendor/types 下的所有包,而不包含来自 ./node_modules/@types 的任何包。所有路径都相对于 tsconfig.json。

    • 相关:
      • types

    • 发布版本:

      2.0

    # 类型 - types

    默认情况下,types 被设置为 []。对于低于 TypeScript 6.0 的版本,默认情况下所有可见的“@types”包都会被包含进编译中。任何外层文件夹的 node_modules/@types 中的包都被视为可见。例如,这意味着 ./node_modules/@types/、../node_modules/@types/、../../node_modules/@types/ 等目录中的包都可见。

    如果指定了 types,则只有列出的包会被包含进全局作用域。例如:

    {
    "": ["node", "jest", "express"]
    }
    }

    这个 tsconfig.json 文件将只包含 ./node_modules/@types/node、./node_modules/@types/jest 和 ./node_modules/@types/express。其他 node_modules/@types/* 下的包将不会被包含。

    这会影响什么?

    此选项不影响 @types/* 如何被包含进你的应用代码中。例如,如果你使用了上面的 compilerOptions 示例,而代码类似下面这样:

    ts
    import * as moment from "moment";
    moment().format("MMMM Do YYYY, h:mm:ss a");

    moment 导入将获得完整的类型。

    设置此选项后,如果不在 types 数组中包含某个模块,那么它:

    • 不会向你的项目添加全局变量(例如 node 中的 process,或 Jest 中的 expect)
    • 其导出不会出现在自动导入建议中

    此功能与 typeRoots 的不同之处在于,它只用于指定你希望包含的确切类型,而 typeRoots 支持表示你想要特定文件夹。

    • 相关:
      • typeRoots

    • 发布于:

      2.0

    #输出

    # 声明 - declaration

    为项目中的每个 TypeScript 或 JavaScript 文件生成 .d.ts 文件。这些 .d.ts 文件是描述模块外部 API 的类型定义文件。借助 .d.ts 文件,TypeScript 之类的工具可以为无类型代码提供智能提示和准确的类型。

    当 declaration 设为 true 时,用下面这段 TypeScript 代码运行编译器:

    ts
    export let helloWorld = "hi";
    Try

    将生成如下 index.js 文件:

    ts
    export let helloWorld = "hi";
     
    Try

    以及对应的 helloWorld.d.ts:

    ts
    export declare let helloWorld: string;
     
    Try

    在处理 JavaScript 文件的 .d.ts 文件时,你可能需要使用 emitDeclarationOnly 或使用 outDir,以确保 JavaScript 文件不会被覆盖。

    • 默认值:

      true,前提是启用 composite;否则为 false。

    • 相关:
      • declarationDir

      • emitDeclarationOnly

    • 发布于:

      1.0

    # 声明目录 - declarationDir

    提供一种方式来配置声明文件输出到的根目录。

    example
    ├── index.ts
    ├── package.json
    └── tsconfig.json

    使用这个 tsconfig.json:

    {
    "": true,
    "": "./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 文件。

    如果你使用项目引用,强烈建议开启此选项。

    • 发布于:

      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 代码:

    ts
    const str = "Hello!";
    for (const s of str) {
    console.log(s);
    }
    Try

    未启用 downlevelIteration 时,对任何对象使用 for / of 循环都会被降级为传统的 for 循环:

    ts
    "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

    这通常符合人们的预期,但并不完全符合 ECMAScript 迭代协议。某些字符串,例如 emoji(😜),其 .length 为 2(甚至更多!),但在 for-of 循环中应作为 1 个单元迭代。更详细的解释请参阅 Jonathan New 的这篇博文。

    启用 downlevelIteration 后,TypeScript 会使用一个辅助函数来检查 Symbol.iterator 的实现(原生的或 polyfill)。如果缺少该实现,就会回退到基于索引的迭代。

    ts
    "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

    你也可以通过 tslib,借助 importHelpers 来减少内联 JavaScript 的数量:

    ts
    "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 并不会提高合规性。

    示例:对数组展开的影响

    这是一个数组展开:

    js
    // Make a new array whose elements are 1 followed by the elements of arr2
    const arr = [1, ...arr2];

    根据描述,降级到 ES5 听起来很容易:

    js
    // The same, right?
    const arr = [1].concat(arr2);

    然而,在某些罕见情况下,这会产生可观察到的差异。

    例如,如果源数组缺少一个或多个元素(存在空洞),展开语法会把每个空位替换为 undefined,而 .concat 会保持它们不变。

    js
    // Make an array where the element at index 1 is missing
    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(如果存在)来更准确地模拟 ES 6 行为。

    • 相关:
      • 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 代码:

    ts
    export function fn(arr: number[]) {
    const arr2 = [1, ...arr];
    }

    开启 downlevelIteration,而 importHelpers 仍为 false 时:

    ts
    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);
    }
     
    Try

    然后同时开启 downlevelIteration 和 importHelpers:

    ts
    import { __read, __spreadArray } from "tslib";
    export function fn(arr) {
    var arr2 = __spreadArray([1], __read(arr), false);
    }
     
    Try

    当你自己提供这些函数的实现时,可以使用 noEmitHelpers。

    • 相关:
      • noEmitHelpers

      • downlevelIteration

    • 发布于:

      2.1

    # 内联源码映射 - inlineSourceMap

    设置此选项后,TypeScript 不会写出 .js.map 文件来提供源码映射,而是将源码映射内容嵌入 .js 文件中。这会使 JS 文件变大,但在某些场景下可能很方便。例如,你可能想在不允许提供 .map 文件的 Web 服务器上调试 JS 文件。

    与 sourceMap 互斥。

    例如,使用下面这段 TypeScript 代码:

    ts
    const helloWorld = "hi";
    console.log(helloWorld);

    会转换为以下 JavaScript:

    ts
    "use strict";
    const helloWorld = "hi";
    console.log(helloWorld);
     
    Try

    然后启用 inlineSourceMap 进行构建,文件底部会有一条注释,其中包含该文件的源码映射。

    ts
    "use strict";
    const helloWorld = "hi";
    console.log(helloWorld);
    //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ==
    Try
    • 发布于:

      1.5

    # 内联源码 - inlineSources

    设置此选项后,TypeScript 会将 .ts 文件的原始内容作为嵌入字符串包含在源码映射中(使用源码映射的 sourcesContent 属性)。这通常与 inlineSourceMap 适用的场景相同。

    需要设置 sourceMap 或 inlineSourceMap 之一。

    例如,使用下面这段 TypeScript 代码:

    ts
    const helloWorld = "hi";
    console.log(helloWorld);
    Try

    默认情况下会转换为以下 JavaScript:

    ts
    "use strict";
    const helloWorld = "hi";
    console.log(helloWorld);
     
    Try

    然后同时启用 inlineSources 和 inlineSourceMap 进行构建,文件底部会有一条注释,其中包含该文件的源码映射。注意,结尾部分与 inlineSourceMap 中的示例不同,因为此时源码映射也包含了原始源代码。

    ts
    "use strict";
    const helloWorld = "hi";
    console.log(helloWorld);
    //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19
    Try
    • 发布于:

      1.5

    # 源码映射根路径 - mapRoot

    指定调试器查找映射文件的位置,以替代默认的生成位置。此字符串会在源码映射中按原样使用,例如:

    {
    "": true,
    "": "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 中使用这个 async 函数需要类似 await 的函数和类似 generator 的函数才能运行:

    ts
    const getAPI = async (url: string) => {
    // Get API
    return {};
    };
    Try

    这会生成大量 JavaScript 代码:

    ts
    "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*/, {}];
    });
    }); };
     
    Try

    你可以通过此标志把它们替换为你自己的全局实现:

    ts
    "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*/, {}];
    });
    }); };
     
    Try
    • 相关:
      • importHelpers

    • 发布于:

      1.5

    # 出错时不输出 - noEmitOnError

    如果有任何错误被报告,则不输出编译器产物文件,例如 JavaScript 源代码、源码映射或声明文件。

    该选项默认为 false,这样在类似监视模式的环境中会更方便:你可能希望在确认所有错误都已解决之前,先在另一个环境中看到代码更改的结果。

    • 发布于:

      1.4

    # 输出目录 - outDir

    如果指定了此选项,.js 文件(以及 .d.ts、.js.map 等)将输出到此目录中。原始源文件的目录结构会被保留;如果计算出的根目录不符合你的预期,请参阅 rootDir。

    如果未指定,.js 文件将与生成它们的 .ts 文件输出在同一目录中:

    sh
    $ tsc
    example
    ├── index.js
    └── index.ts

    使用如下 tsconfig.json:

    {
    "": "dist"
    }
    }

    使用这些设置运行 tsc,文件会被移动到指定的 dist 文件夹中:

    sh
    $ tsc
    example
    ├── dist
    │ └── index.js
    ├── index.ts
    └── tsconfig.json
    • 相关:
      • out

      • outFile

    • 发布于:

      1.0

    # 输出文件 - outFile

    如果指定了此选项,所有全局(非模块)文件都会被合并到所指定的单个输出文件中。

    如果 module 为 system 或 amd,那么在所有全局内容之后,所有模块文件也会被合并到此文件中。

    注意:除非 module 为 None、System 或 AMD,否则不能使用 outFile。此选项不能用于打包 CommonJS 或 ES6 模块。

    • 相关:
      • out

      • outDir

    • 发布于:

      1.6

    # 保留 const 枚举 - preserveConstEnums

    不要在生成的代码中擦除 const enum 声明。const enum 通过输出枚举值而不是引用来减少应用运行时的整体内存占用。

    例如,对于这段 TypeScript:

    ts
    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 中完全移除对该枚举的引用。

    ts
    "use strict";
    const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;
    if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {
    console.log("That is a great choice.");
    }
     
    Try

    当 preserveConstEnums 设为 true 时,enum 在运行时存在,数字仍会被输出。

    ts
    "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 enums 只成为源代码层面的特性,在运行时不留痕迹。

    • 默认值:

      如果启用 isolatedModules 则为 true;否则为 false。

    • 发布版本:

      1.4

    # 移除注释 - removeComments

    在转换为 JavaScript 时从 TypeScript 文件中剥离所有注释。默认为 false。

    例如,这是一个带有 JSDoc 注释的 TypeScript 文件:

    ts
    /** The translation of 'Hello world' into Portuguese */
    export const helloWorldPTBR = "Olá Mundo";

    当 removeComments 设为 true 时:

    ts
    export const helloWorldPTBR = "Olá Mundo";
     
    Try

    未设置 removeComments 或将其设为 false 时:

    ts
    /** The translation of 'Hello world' into Portuguese */
    export const helloWorldPTBR = "Olá Mundo";
     
    Try

    这意味着你的注释会出现在 JavaScript 代码中。

    • 发布版本:

      1.0

    # 源码映射 - sourceMap

    启用 sourcemap 文件的生成。这些文件让调试器和其他工具在实际处理输出的 JavaScript 文件时能够显示原始的 TypeScript 源代码。源码映射文件会作为 .js.map(或 .jsx.map)文件输出到对应的 .js 输出文件旁边。

    这些 .js 文件则会包含一条 sourcemap 注释,向外部工具指明文件的位置,例如:

    ts
    // helloWorld.ts
    export declare const helloWorld = "hi";

    在 sourceMap 设为 true 时编译会创建以下 JavaScript 文件:

    js
    // helloWorld.js
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.helloWorld = "hi";
    //# sourceMappingURL=// helloWorld.js.map

    这还会生成如下 JSON 映射:

    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 文件的位置,而不是相对源位置。该字符串在 source-map 中会按原样处理,你可以使用路径或 URL:

    {
    "": true,
    "": "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。

    ts
    /**
    * 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;
    }
    Try

    将该标志设为 false(默认)时:

    ts
    /**
    * 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;
     
    Try

    当 stripInternal 设为 true 时,输出的 d.ts 会被删减。

    ts
    /** Calculate how much someone earns in a week */
    export declare function weeklySalary(dayRate: number): number;
     
    Try

    JavaScript 输出仍然相同。

    • 内部
    • 发布版本:

      1.5

    #JavaScript 支持

    # 允许 JS - allowJs

    允许在项目中导入 JavaScript 文件,而不只是 .ts 和 .tsx 文件。例如,这个 JS 文件:

    js
    // @filename: card.js
    export const defaultCardDeck = "Heart";
    Try

    当它被导入 TypeScript 文件时会报错:

    ts
    // @filename: index.ts
    import { defaultCardDeck } from "./card";
     
    console.log(defaultCardDeck);
    Try

    启用 allowJs 后可以正常导入:

    ts
    // @filename: index.ts
    import { defaultCardDeck } from "./card";
     
    console.log(defaultCardDeck);
    Try

    该标志可用于向 JS 项目逐步添加 TypeScript 文件,允许 .ts 和 .tsx 文件与现有 JavaScript 文件并存。

    它也可以与 declaration 和 emitDeclarationOnly 一起使用,来为 JS 文件创建声明。

    • 默认值:

      false,除非设置了 checkJs

    • 相关:
      • checkJs

      • emitDeclarationOnly

    • 发布版本:

      1.8

    # 检查 JS - checkJs

    与 allowJs 配合使用。启用 checkJs 后,JavaScript 文件中的错误会被报告出来。这相当于在项目中包含的所有 JavaScript 文件顶部加上 // @ts-check。

    例如,根据 TypeScript 随附的 parseFloat 类型定义,这段 JavaScript 是不正确的:

    js
    // parseFloat only takes a string
    module.exports.pi = parseFloat(3.142);

    当它被导入 TypeScript 模块时:

    ts
    // @filename: constants.js
    module.exports.pi = parseFloat(3.142);
     
    // @filename: index.ts
    import { pi } from "./constants";
    console.log(pi);
    Try

    你不会看到任何错误。不过,如果开启 checkJs,你就会收到来自该 JavaScript 文件的错误消息。

    ts
    // @filename: constants.js
    module.exports.pi = parseFloat(3.142);
    Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.
     
    // @filename: index.ts
    import { pi } from "./constants";
    console.log(pi);
    Try
    • 相关:
      • allowJs

      • emitDeclarationOnly

    • 发布版本:

      2.3

    # Node 模块 JS 最大深度 - maxNodeModuleJsDepth

    在 node_modules 下搜索并加载 JavaScript 文件的最大依赖深度。

    该标志只能在启用 allowJs 时使用,如果你想为 node_modules 中的所有 JavaScript 推断类型,就可以用它。

    理想情况下它应保持为 0(默认值),并使用 d.ts 文件显式定义模块的形状。不过,在某些情况下,你可能会以牺牲速度和潜在准确性为代价开启它。

    • 发布版本:

      2.0

    #编辑器支持

    # 禁用大小限制 - disableSizeLimit

    为避免在处理非常大的 JavaScript 项目时可能出现的内存膨胀问题,TypeScript 分配的内存量有上限。开启此标志将移除该限制。

    • 发布版本:

      2.0

    # 插件 - plugins

    要在编辑器中运行的语言服务插件列表。

    语言服务插件是一种基于已有的 TypeScript 文件向用户提供附加信息的方式。它们可以增强 TypeScript 与编辑器之间已有的消息,也可以提供自己的错误消息。

    例如:

    VS Code 允许扩展自动包含语言服务插件,因此你的编辑器中可能已经有一些插件在运行,而无需在 tsconfig.json 中定义它们。

    • 发布版本:

      2.2

    #互操作约束

    # 允许合成默认导入 - allowSyntheticDefaultImports

    当设为 true 时,allowSyntheticDefaultImports 允许你编写这样的导入:

    ts
    import React from "react";

    而不是:

    ts
    import * as React from "react";

    当模块没有显式指定默认导出时。

    例如,未将 allowSyntheticDefaultImports 设为 true 时:

    ts
    // @filename: utilFunctions.js
    const getStringLength = (str) => str.length;
     
    module.exports = {
    getStringLength,
    };
     
    // @filename: index.ts
    import utils from "./utilFunctions";
     
    const count = utils.getStringLength("Check JS");
    Try

    这段代码会报错,因为不存在可以导入的 default 对象,尽管感觉上应该有。为方便起见,像 Babel 这样的转译器会在没有创建默认导出时自动创建一个,使模块看起来更像:

    js
    // @filename: utilFunctions.js
    const getStringLength = (str) => str.length;
    const allFunctions = {
    getStringLength,
    };
    module.exports = allFunctions;
    module.exports.default = allFunctions;

    该标志不影响 TypeScript 输出的 JavaScript,它只用于类型检查。这个选项让 TypeScript 的行为与 Babel 保持一致,后者会输出额外的代码,让使用模块的默认导出变得更方便。

    # 仅可擦除语法 - erasableSyntaxOnly

    自 v23.6 起,Node.js 支持直接运行 TypeScript 文件;不过,该模式只支持不具备运行时语义的 TypeScript 专有语法。换句话说,必须能够轻松地从文件中擦除任何 TypeScript 专有语法,只留下有效的 JavaScript 文件。

    这意味着不支持以下构造:

    • enum 声明
    • 带有运行时代码的 namespace 和 module
    • 类中的参数属性
    • 非 ECMAScript 的 import = 与 export = 赋值
    • <prefix> 形式的类型断言
    ts
    // ❌ error: An `import ... = require(...)` alias
    import foo = require("foo");
    // ❌ error: A namespace with runtime code.
    namespace container {
    foo.method();
    export type Bar = string;
    }
    // ❌ error: An `import =` alias
    import Bar = container.Bar;
    class Point {
    // ❌ error: Parameter properties
    constructor(public x: number, public y: number) {}
    }
    // ❌ error: An `export =` assignment.
    export = Point;
    // ❌ error: An enum declaration.
    enum Direction {
    Up,
    Down,
    Left,
    Right,
    }
    // ❌ error: <prefix>-style type assertion.
    const num = <number>1;

    类似 ts-blank-space 或 Amaro(Node.js 中类型擦除的底层库)这样的工具也有相同的限制。如果遇到不满足这些要求的代码,这些工具会提供有用的错误消息,但你在真正尝试运行之前,仍然不会发现代码无法运行。

    --erasableSyntaxOnly 标志会让 TypeScript 对大多数具有运行时行为的 TypeScript 专有构造报错。

    ts
    class C {
    constructor(public x: number) { }
    // ~~~~~~~~~~~~~~~~
    // error! This syntax is not allowed when 'erasableSyntaxOnly' is enabled.
    }
    }

    通常,你会希望将此标志与 --verbatimModuleSyntax 结合使用,后者确保模块包含适当的导入语法,并且不会发生导入省略。

      # ES 模块互操作 - esModuleInterop

      默认情况下(esModuleInterop 为 false 或未设置),TypeScript 将 CommonJS/AMD/UMD 模块当作类似 ES6 模块来处理。这样做时,有两个部分被证明是错误的假设:

      • 像 import * as moment from "moment" 这样的命名空间导入,其行为与 const moment = require("moment") 相同

      • 像 import moment from "moment" 这样的默认导入,其行为与 const moment = require("moment").default 相同

      这种不匹配导致了以下两个问题:

      • ES6 模块规范规定,命名空间导入(import * as x)只能是对象;而 TypeScript 将其等同于 = require("x"),于是允许把该导入当作函数来调用。按照规范,这是不合法的。

      • 虽然这符合 ES6 模块规范,但大多数使用 CommonJS/AMD/UMD 模块的库并没有像 TypeScript 的实现那样严格遵循规范。

      开启 esModuleInterop 会修复 TypeScript 转译出的代码中的这两个问题。第一个问题通过改变编译器中的行为来解决,第二个问题则由两个新的辅助函数解决,它们提供一个 shim 以确保生成的 JavaScript 中的兼容性:

      ts
      import * as fs from "fs";
      import _ from "lodash";
      fs.readFileSync("file.txt", "utf8");
      _.chunk(["a", "b", "c", "d"], 2);

      禁用 esModuleInterop 时:

      ts
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      const fs = require("fs");
      const lodash_1 = require("lodash");
      fs.readFileSync("file.txt", "utf8");
      lodash_1.default.chunk(["a", "b", "c", "d"], 2);
       
      Try

      将 esModuleInterop 设为 true 时:

      ts
      "use strict";
      var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
      if (k2 === undefined) k2 = k;
      var desc = Object.getOwnPropertyDescriptor(m, k);
      if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
      }
      Object.defineProperty(o, k2, desc);
      }) : (function(o, m, k, k2) {
      if (k2 === undefined) k2 = k;
      o[k2] = m[k];
      }));
      var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
      Object.defineProperty(o, "default", { enumerable: true, value: v });
      }) : function(o, v) {
      o["default"] = v;
      });
      var __importStar = (this && this.__importStar) || (function () {
      var ownKeys = function(o) {
      ownKeys = Object.getOwnPropertyNames || function (o) {
      var ar = [];
      for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
      return ar;
      };
      return ownKeys(o);
      };
      return function (mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
      __setModuleDefault(result, mod);
      return result;
      };
      })();
      var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
      };
      Object.defineProperty(exports, "__esModule", { value: true });
      const fs = __importStar(require("fs"));
      const lodash_1 = __importDefault(require("lodash"));
      fs.readFileSync("file.txt", "utf8");
      lodash_1.default.chunk(["a", "b", "c", "d"], 2);
       
      Try

      注意:命名空间导入 import * as fs from "fs" 只包含被导入对象上自有的属性(基本上是在对象上直接设置的属性,而非通过原型链设置的属性)。如果你导入的模块使用继承属性定义其 API,则需要使用默认导入形式(import fs from "fs"),或禁用 esModuleInterop。

      注意:启用 importHelpers 可以让输出的 JS 更精简:

      ts
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      const tslib_1 = require("tslib");
      const fs = tslib_1.__importStar(require("fs"));
      const lodash_1 = tslib_1.__importDefault(require("lodash"));
      fs.readFileSync("file.txt", "utf8");
      lodash_1.default.chunk(["a", "b", "c", "d"], 2);
       
      Try

      启用 esModuleInterop 也会启用 allowSyntheticDefaultImports。

      • 推荐
      • 默认值:

        如果 module 为 node16、nodenext 或 preserve,则为 true;否则为 false。

      • 相关:
        • allowSyntheticDefaultImports

      • 发布版本:

        2.7

      # 强制文件名大小写一致 - forceConsistentCasingInFileNames

      TypeScript 遵循其运行所在文件系统的大小写敏感规则。如果一些开发者使用区分大小写的文件系统,而另一些不区分,就可能出问题。如果某个文件尝试通过指定 ./FileManager.ts 来导入 fileManager.ts,在不区分大小写的文件系统中能找到该文件,但在区分大小写的文件系统中则找不到。

      设置此选项后,如果程序尝试以与磁盘上不同的大小写包含文件,TypeScript 将报错。

      • 推荐
      • 默认值:

        true

      • 发布于:

        1.8

      # 隔离声明 - isolatedDeclarations

      要求对导出提供足够的类型标注,以便其他工具能轻松生成声明文件。

      更多信息,请参阅 5.5 发行说明

      • 发布于:

        5.5

      # 隔离模块 - isolatedModules

      虽然你可以用 TypeScript 从 TypeScript 代码生成 JavaScript 代码,但也常用 Babel 等其他转译器来做这件事。然而,其他转译器一次只能处理单个文件,这意味着它们无法应用依赖理解完整类型系统的代码转换。这一限制也适用于某些构建工具使用的 TypeScript ts.transpileModule API。

      这些限制会给 const enum 和 namespace 等某些 TypeScript 特性带来运行时问题。设置 isolatedModules 标志会让 TypeScript 在你编写无法被单文件转译过程正确解释的代码时发出警告。

      它不会改变你的代码的行为,也不会改变 TypeScript 的检查与输出过程的行为。

      以下是一些在启用 isolatedModules 时无法工作的代码示例。

      导出非值标识符

      在 TypeScript 中,你可以导入一个类型,然后再导出它:

      ts
      import { someType, someFunction } from "someModule";
       
      someFunction();
       
      export { someType, someFunction };
      Try

      由于 someType 没有值,输出的 export 不会尝试导出它(在 JavaScript 中那会是一个运行时错误):

      js
      export { someFunction };

      单文件转译器不知道 someType 是否产生值,因此导出一个仅指代类型的名称是错误的。

      非模块文件

      如果设置了 isolatedModules,命名空间只允许出现在模块中(即带有某种 import/export 形式)。如果在非模块文件中发现命名空间,就会报错:

      ts
      namespace Instantiated {
      Namespaces are not allowed in global script files when 'isolatedModules' is enabled. If this file is not intended to be a global script, set 'moduleDetection' to 'force' or add an empty 'export {}' statement.1280Namespaces are not allowed in global script files when 'isolatedModules' is enabled. If this file is not intended to be a global script, set 'moduleDetection' to 'force' or add an empty 'export {}' statement.
      export const x = 1;
      }
      Try

      此限制不适用于 .d.ts 文件。

      对 const enum 成员的引用

      在 TypeScript 中,当你引用 const enum 成员时,该引用会在输出的 JavaScript 中被替换为其实际值。将这段 TypeScript:

      ts
      declare const enum Numbers {
      Zero = 0,
      One = 1,
      }
      console.log(Numbers.Zero + Numbers.One);
      Try

      改为如下 JavaScript:

      ts
      "use strict";
      console.log(0 + 1);
       
      Try

      如果不了解这些成员的值,其他转译器就无法替换对 Numbers 的引用;若放任不管,这会在运行时出错(因为运行时不存在 Numbers 对象)。因此,设置 isolatedModules 后,引用环境 const enum 成员会报错。

      这是为了与 Node.js 中的同名标志保持一致;该标志不会解析符号链接的真实路径。

      此标志的行为也与 Webpack 的 resolve.symlinks 选项相反(即把 TypeScript 的 preserveSymlinks 设为 true 相当于把 Webpack 的 resolve.symlinks 设为 false,反之亦然)。

      启用后,对模块和包的引用(例如 import 和 /// <reference type="..." /> 指令)都相对于符号链接文件所在位置解析,而不是相对于符号链接解析到的路径。

      • 发布于:

        2.5

      # 逐字模块语法 - verbatimModuleSyntax

      默认情况下,TypeScript 会做一件称为导入省略的事情。基本上,如果你写类似

      ts
      import { Car } from "./car";
      export function drive(car: Car) {
      // ...
      }

      TypeScript 检测到你仅将导入用于类型,就会完全删除该导入。输出的 JavaScript 可能类似这样:

      js
      export function drive(car) {
      // ...
      }

      大多数情况下这是好事,因为如果 Car 不是从 ./car 导出的值,我们会在运行时出错。

      但它确实为某些边界情况增加了一层复杂性。例如,注意没有 import "./car"; 这样的语句——导入被完全删除了。对于是否具有副作用的模块,这实际上会产生差别。

      TypeScript 针对 JavaScript 的输出策略还有几层复杂性——导入省略并不总是只由导入的使用方式决定——它常常还会参考值的声明方式。因此,像下面这样的代码

      ts
      export { Car } from "./car";

      应当保留还是删除,并不总是很清楚。如果 Car 是用 class 之类的东西声明的,那么它可以在生成的 JavaScript 文件中保留。但如果 Car 仅被声明为 type 别名或 interface,那么该 JavaScript 文件根本不应导出 Car。

      虽然 TypeScript 或许能依据跨文件的信息做出这些输出决策,但并非每个编译器都能做到。

      导入和导出上的 type 修饰符在一定程度上能帮助处理这些情况。通过使用 type 修饰符,我们可以明确某个导入或导出是否仅用于类型分析,从而可以在 JavaScript 文件中将其完全删除。

      ts
      // This statement can be dropped entirely in JS output
      import type * as car from "./car";
      // The named import/export 'Car' can be dropped in JS output
      import { type Car } from "./car";
      export { type Car } from "./car";

      type 修饰符单独使用并不太有用 —— 默认情况下,模块省略仍会丢弃导入,也没有任何机制强制你区分 type 与普通的导入和导出。因此 TypeScript 提供了 --importsNotUsedAsValues 标志来确保你使用 type 修饰符,提供了 --preserveValueImports 来阻止部分模块省略行为,还提供了 --isolatedModules 来确保你的 TypeScript 代码能在不同编译器之间正常工作。遗憾的是,理解这 3 个标志的细微之处并不容易,而且仍存在一些行为出人意料的边界情况。

      TypeScript 5.0 引入了一个名为 --verbatimModuleSyntax 的新选项来简化这一局面。规则简单得多 —— 任何没有 type 修饰符的导入或导出都会被保留。任何使用 type 修饰符的内容都会被完全丢弃。

      ts
      // Erased away entirely.
      import type { A } from "a";
      // Rewritten to 'import { b } from "bcd";'
      import { b, type c, type d } from "bcd";
      // Rewritten to 'import {} from "xyz";'
      import { type xyz } from "xyz";

      使用这个新选项,所见即所得。

      不过,在模块互操作方面,这确实带来了一些影响。在此标志下,当你的设置或文件扩展名暗示了不同的模块系统时,ECMAScript 的 import 和 export 不会被改写成 require 调用。相反,你会得到一个错误。如果你需要生成使用 require 和 module.exports 的代码,就必须使用 TypeScript 早于 ES2015 的模块语法:

      输入 TypeScript 输出 JavaScript
      ts
      import foo = require("foo");
      js
      const foo = require("foo");
      ts
      function foo() {}
      function bar() {}
      function baz() {}
      export = {
      foo,
      bar,
      baz,
      };
      js
      function foo() {}
      function bar() {}
      function baz() {}
      module.exports = {
      foo,
      bar,
      baz,
      };

      尽管这是一项限制,但它确实有助于让一些问题更加明显。例如,在 --module node16 下,很容易忘记设置 type 字段(位于 package.json 中)。结果,开发者会在没有意识到的情况下开始编写 CommonJS 模块而不是 ES 模块,从而得到令人意外的查找规则和 JavaScript 输出。这个新标志确保你对所使用的文件类型是有意为之的,因为语法本身就是刻意设计得不同。

      由于 --verbatimModuleSyntax 提供的方案比 --importsNotUsedAsValues 和 --preserveValueImports 更一致,后两个现有标志正被弃用,以它取而代之。

      更多细节请阅读最初的拉取请求及其提案 issue。

      • 发布版本:

        5.0

      #向后兼容性

      # 字符集 - charset

      在之前的 TypeScript 版本中,此选项控制从磁盘读取文本文件时所使用的编码。如今 TypeScript 假定使用 UTF-8 编码,但会正确地检测 UTF-16(BE 和 LE)或 UTF-8 BOM。

      • 已弃用
      • 默认值:

        utf8

      • 发布版本:

        1.0

      # 未用作值的导入 - importsNotUsedAsValues

      已弃用,请改用 verbatimModuleSyntax。

      此标志控制 import 的工作方式,共有 3 个不同的选项:

      • remove:默认行为,丢弃仅引用类型的 import 语句。

      • preserve:保留所有值或类型从未被使用的 import 语句。这可能导致导入或副作用被保留。

      • error:保留所有导入(与 preserve 选项相同),但当某个值导入仅被用作类型时会报错。如果你希望确保没有值被意外导入,同时仍让副作用导入保持显式,这可能很有用。

      此标志之所以有效,是因为你可以使用 import type 显式创建一条永远不会输出到 JavaScript 中的 import 语句。

      • 默认值:

        remove

      • 允许值:
        • remove

        • preserve

        • error

      • 相关:
        • preserveValueImports

        • verbatimModuleSyntax

      • 发布版本:

        3.8

      # keyof 仅限字符串 - keyofStringsOnly

      当 keyof 类型运算符应用于带有字符串索引签名的类型时,此标志会让它返回 string 而不是 string | number。

      此标志用于帮助人们保留 TypeScript 2.9 发布之前的这种行为。

      • 已弃用
      • 发布版本:

        2.9

      # 不隐式添加 use strict - noImplicitUseStrict

      你本不需要这个选项。默认情况下,当把模块文件输出到非 ES6 目标时,TypeScript 会在文件顶部生成一段 "use strict"; 前导语句。此设置会禁用该前导语句。

      • 发布版本:

        1.8

      # 关闭严格泛型检查 - noStrictGenericChecks

      在比较两个泛型函数时,TypeScript 会统一类型参数。

      ts
      type A = <T, U>(x: T, y: U) => [T, U];
      type B = <S>(x: S, y: S) => [S, S];
       
      function f(a: A, b: B) {
      b = a; // Ok
      a = b; // Error
      Type 'B' is not assignable to type 'A'. Types of parameters 'y' and 'y' are incompatible. Type 'U' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.2322Type 'B' is not assignable to type 'A'. Types of parameters 'y' and 'y' are incompatible. Type 'U' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.
      }
      Try

      此标志可用于移除这项检查。

      • 发布版本:

        2.5

      # 输出 - out

      请改用 outFile。

      out 选项计算最终文件位置的方式不可预测且不一致。此选项仅为向后兼容而保留,已被弃用。

      • 已弃用
      • 相关:
        • outDir

        • outFile

      • 发布版本:

        1.0

      # 保留值导入 - preserveValueImports

      已弃用,请改用 verbatimModuleSyntax。

      在某些情况下,TypeScript 无法检测出你正在使用某个导入。例如,看下面的代码:

      ts
      import { Animal } from "./animal.js";
      eval("console.log(new Animal().isDangerous())");

      或者使用 Svelte、Vue 等“编译为 HTML”语言的代码。preserveValueImports 会阻止 TypeScript 移除该导入,即使它看起来未被使用。

      与 isolatedModules 结合使用时:导入的类型必须标记为仅类型,因为一次只处理单个文件的编译器无法得知这些导入究竟是看似未被使用的值,还是必须移除以避免运行时崩溃的类型。

      • 相关:
        • isolatedModules

        • importsNotUsedAsValues

        • verbatimModuleSyntax

      • 发布版本:

        4.5

      # 抑制多余属性错误 - suppressExcessPropertyErrors

      这会禁用多余属性错误的报告,例如以下示例中显示的错误:

      ts
      type Point = { x: number; y: number };
      const p: Point = { x: 1, y: 3, m: 10 };
      Object literal may only specify known properties, and 'm' does not exist in type 'Point'.2353Object literal may only specify known properties, and 'm' does not exist in type 'Point'.
      Try

      此标志的加入是为了帮助人们迁移到 TypeScript 1.6 中对新对象字面量更严格的检查。

      在现代代码库中我们不推荐使用此标志,对于个别需要的情况,你可以使用 // @ts-ignore 来抑制。

      • 发布版本:

        1.6

      # 抑制隐式 Any 索引错误 - suppressImplicitAnyIndexErrors

      开启 suppressImplicitAnyIndexErrors 会抑制在索引对象时关于隐式 any 的错误报告,如下例所示:

      ts
      const obj = { x: 10 };
      console.log(obj["foo"]);
      Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type '{ x: number; }'. Property 'foo' does not exist on type '{ x: number; }'.7053Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type '{ x: number; }'. Property 'foo' does not exist on type '{ x: number; }'.
      Try

      使用 suppressImplicitAnyIndexErrors 是相当激进的做法。建议改用 @ts-ignore 注释:

      ts
      const obj = { x: 10 };
      // @ts-ignore
      console.log(obj["foo"]);
      Try
      • 相关:
        • noImplicitAny

      • 发布版本:

        1.4

      #语言与环境

      # 输出装饰器元数据 - emitDecoratorMetadata

      启用为装饰器输出类型元数据的实验性支持,该功能与 reflect-metadata 模块配合使用。

      例如,下面是 TypeScript 代码

      ts
      function LogMethod(
      target: any,
      propertyKey: string | symbol,
      descriptor: PropertyDescriptor
      ) {
      console.log(target);
      console.log(propertyKey);
      console.log(descriptor);
      }
       
      class Demo {
      @LogMethod
      public foo(bar: number) {
      // do nothing
      }
      }
       
      const demo = new Demo();
      Try

      当 emitDecoratorMetadata 未设为 true(默认)时,输出的 JavaScript 是:

      ts
      "use strict";
      var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
      };
      function LogMethod(target, propertyKey, descriptor) {
      console.log(target);
      console.log(propertyKey);
      console.log(descriptor);
      }
      class Demo {
      foo(bar) {
      // do nothing
      }
      }
      __decorate([
      LogMethod
      ], Demo.prototype, "foo", null);
      const demo = new Demo();
       
      Try

      当 emitDecoratorMetadata 设为 true 时,输出的 JavaScript 是:

      ts
      "use strict";
      var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
      };
      var __metadata = (this && this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
      };
      function LogMethod(target, propertyKey, descriptor) {
      console.log(target);
      console.log(propertyKey);
      console.log(descriptor);
      }
      class Demo {
      foo(bar) {
      // do nothing
      }
      }
      __decorate([
      LogMethod,
      __metadata("design:type", Function),
      __metadata("design:paramtypes", [Number]),
      __metadata("design:returntype", void 0)
      ], Demo.prototype, "foo", null);
      const demo = new Demo();
       
      Try
      • 相关:
        • experimentalDecorators

      • 发布版本:

        1.5

      # 实验性装饰器 - experimentalDecorators

      启用装饰器的实验性支持,这是早于 TC39 标准化流程的装饰器版本。

      装饰器是一种尚未完全被批准纳入 JavaScript 规范的语言特性。这意味着 TypeScript 中的实现版本可能与 TC39 最终决定的 JavaScript 实现不同。

      你可以在手册中进一步了解 TypeScript 对装饰器的支持。

      • 相关:
        • emitDecoratorMetadata

      • 发布版本:

        1.5

      # JSX - jsx

      控制 JSX 结构在 JavaScript 文件中的输出方式。这只影响源自 .tsx 文件的 JS 文件的输出。

      • react-jsx:输出 .js 文件,其中 JSX 被转换为针对生产优化的 _jsx 调用
      • react-jsxdev:输出 .js 文件,其中 JSX 被转换为仅用于开发的 _jsx 调用
      • preserve:输出 .jsx 文件,JSX 保持不变
      • react-native:输出 .js 文件,JSX 保持不变
      • react:输出 .js 文件,JSX 被转换为等价的 React.createElement 调用

      例如

      这段示例代码:

      tsx
      export const HelloWorld = () => <h1>Hello world</h1>;

      React:"react-jsx"[1]

      tsx
      import { jsx as _jsx } from "react/jsx-runtime";
      export const HelloWorld = () => _jsx("h1", { children: "Hello world" });
       
      Try

      React 开发模式转换:"react-jsxdev"[1]

      tsx
      import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
      const _jsxFileName = "/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/index.tsx";
      export const HelloWorld = () => _jsxDEV("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 9, columnNumber: 33 }, this);
       
      Try

      保留:"preserve"

      tsx
      import React from 'react';
      export const HelloWorld = () => <h1>Hello world</h1>;
       
      Try

      React Native:"react-native"

      tsx
      import React from 'react';
      export const HelloWorld = () => <h1>Hello world</h1>;
       
      Try

      旧版 React 运行时:"react"

      tsx
      import React from 'react';
      export const HelloWorld = () => React.createElement("h1", null, "Hello world");
       
      Try

      此选项也可以通过 @jsxRuntime 注释按文件使用。

      对此文件始终使用经典运行时("react"):

      tsx
      /* @jsxRuntime classic */
      export const HelloWorld = () => <h1>Hello world</h1>;

      对此文件始终使用自动运行时("react-jsx"):

      tsx
      /* @jsxRuntime automatic */
      export const HelloWorld = () => <h1>Hello world</h1>;
      • 允许值:
        • preserve

        • react

        • react-native

        • react-jsx

        • react-jsxdev

      • 相关:
        • jsxFactory

        • jsxFragmentFactory

        • jsxImportSource

      • 发布版本:

        1.6

      # JSX 工厂函数 - jsxFactory

      在使用经典 JSX 运行时编译 JSX 元素时,更改在 .js 文件中调用的函数。最常见的变化是:如果使用 preact,则用 "h" 或 "preact.h" 代替默认的 "React.createElement"。

      例如,这个 TSX 文件:

      tsx
      import { h } from "preact";
      const HelloWorld = () => <div>Hello</div>;

      在 jsxFactory: "h" 下看起来像:

      tsx
      const preact_1 = require("preact");
      const HelloWorld = () => (0, preact_1.h)("div", null, "Hello");
       
      Try

      此选项也可以按文件使用,类似于 Babel 的 /** @jsx h */ 指令。

      tsx
      /** @jsx h */
      import { h } from "preact";
      Cannot find module 'preact' or its corresponding type declarations.2307Cannot find module 'preact' or its corresponding type declarations.
       
      const HelloWorld = () => <div>Hello</div>;
      Try

      所选的工厂函数还会影响在回退到全局命名空间之前,在哪里查找 JSX 命名空间(以获取类型检查信息)。

      如果工厂函数定义为 React.createElement(默认),编译器会先检查 React.JSX,再检查全局的 JSX。如果工厂函数定义为 h,则会先检查 h.JSX,再检查全局的 JSX。

      • 默认值:

        React.createElement

      • 允许值:
        • 任何标识符或带点的标识符。

      • 相关:
        • jsx

        • jsxFragmentFactory

        • jsxImportSource

      • 发布版本:

        2.2

      # JSX 片段工厂函数 - jsxFragmentFactory

      指定当使用 jsxFactory 编译器选项以 react JSX 输出为目标时要使用的 JSX 片段工厂函数,例如 Fragment。

      例如,使用此 TSConfig:

      {
      "": "esnext",
      "": "commonjs",
      "": "react",
      "": "h",
      "": "Fragment"
      }
      }

      这个 TSX 文件:

      tsx
      import { h, Fragment } from "preact";
      const HelloWorld = () => (
      <>
      <div>Hello</div>
      </>
      );

      会看起来像:

      tsx
      const preact_1 = require("preact");
      const HelloWorld = () => ((0, preact_1.h)(preact_1.Fragment, null,
      (0, preact_1.h)("div", null, "Hello")));
       
      Try

      此选项也可以按文件使用,类似于 Babel 的 /* @jsxFrag h */ 指令。

      例如:

      tsx
      /** @jsx h */
      /** @jsxFrag Fragment */
       
      import { h, Fragment } from "preact";
      Cannot find module 'preact' or its corresponding type declarations.2307Cannot find module 'preact' or its corresponding type declarations.
       
      const HelloWorld = () => (
      <>
      <div>Hello</div>
      </>
      );
      Try
      • 默认值:

        React.Fragment

      • 相关:
        • jsx

        • jsxFactory

        • jsxImportSource

      • 发布版本:

        4.0

      # JSX 导入源 - jsxImportSource

      声明当以 "react-jsx" 或 "react-jsxdev"(二者在 TypeScript 4.1 中引入)使用 jsx 时,用于导入 jsx 和 jsxs 工厂函数的模块说明符。

      从 React 17 开始,该库支持通过单独的导入进行的新形式 JSX 转换。

      例如,使用以下代码:

      tsx
      import React from "react";
      function App() {
      return <h1>Hello World</h1>;
      }

      使用以下 TSConfig:

      {
      "": "esnext",
      "": "commonjs",
      "": "react-jsx"
      }
      }

      TypeScript 输出的 JavaScript 为:

      tsx
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      const jsx_runtime_1 = require("react/jsx-runtime");
      function App() {
      return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
      }
       
      Try

      例如,如果你想使用 "jsxImportSource": "preact",则需要如下所示的 tsconfig:

      {
      "": "esnext",
      "": "commonjs",
      "": "react-jsx",
      "": "preact",
      "": ["preact"]
      }
      }

      它会生成类似以下的代码:

      tsx
      function App() {
      return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
      }
       
      Try

      或者,你可以使用逐文件的 pragma 来设置此选项,例如:

      tsx
      /** @jsxImportSource preact */
      export function App() {
      return <h1>Hello World</h1>;
      }

      这样会为 _jsx 工厂添加 preact/jsx-runtime 作为导入。

      注意:为了让这一功能按你的预期工作,你的 tsx 文件必须包含 export 或 import,以便被视为模块。

      • 默认值:

        react

      • 相关:
        • jsx

        • jsxFactory

      • 发布版本:

        4.1

      # 库 - lib

      TypeScript 包含一组针对内置 JS API(如 Math)的默认类型定义,以及针对浏览器环境中存在的对象(如 document)的类型定义。TypeScript 还包含与你指定的 target 相匹配的较新 JS 特性的 API;例如,如果 target 为 ES6 或更高版本,就可以使用 Map 的定义。

      你可能会出于以下几个原因想要更改这些定义:

      • 你的程序不在浏览器中运行,因此你不需要 "dom" 类型定义
      • 你的运行时平台提供了某些 JavaScript API 对象(可能是通过 polyfill),但尚不支持给定 ECMAScript 版本的全部语法
      • 你为较高版本的 ECMAScript 提供了部分(但并非全部)polyfill 或原生实现

      在 TypeScript 4.5 中,lib 文件可以被 npm 模块覆盖,更多信息请参阅这篇博文。

      高层库

      名称 内容
      ES5 所有 ES5 功能的核心定义
      ES2015 ES2015(又称 ES6)中可用的额外 API:array.find、Promise、Proxy、Symbol、Map、Set、Reflect 等。
      ES6 “ES2015”的别名
      ES2016 ES2016 中可用的额外 API:array.include 等。
      ES7 “ES2016”的别名
      ES2017 ES2017 中可用的额外 API:Object.entries、Object.values、Atomics、SharedArrayBuffer、date.formatToParts、类型化数组等。
      ES2018 ES2018 中可用的额外 API:async 可迭代对象、promise.finally、Intl.PluralRules、regexp.groups 等。
      ES2019 ES2019 中可用的额外 API:array.flat、array.flatMap、Object.fromEntries、string.trimStart、string.trimEnd 等。
      ES2020 ES2020 中可用的额外 API:string.matchAll 等。
      ES2021 ES2021 中可用的额外 API:promise.any、string.replaceAll 等。
      ES2022 ES2022 中可用的额外 API:array.at、RegExp.hasIndices 等。
      ES2023 ES2023 中可用的额外 API:array.with、array.findLast、array.findLastIndex、array.toSorted、array.toReversed 等。
      ESNext ESNext 中可用的额外 API:这些 API 会随着 JavaScript 规范的演进而变化。
      DOM DOM 定义:window、document 等。
      WebWorker WebWorker 上下文中可用的 API
      ScriptHost Windows 脚本宿主系统 相关的 API

      单个库组件

      名称
      DOM.Iterable
      ES2015.Core
      ES2015.Collection
      ES2015.Generator
      ES2015.Iterable
      ES2015.Promise
      ES2015.Proxy
      ES2015.Reflect
      ES2015.Symbol
      ES2015.Symbol.WellKnown
      ES2016.Array.Include
      ES2017.object
      ES2017.Intl
      ES2017.SharedMemory
      ES2017.String
      ES2017.TypedArrays
      ES2018.Intl
      ES2018.Promise
      ES2018.RegExp
      ES2019.Array
      ES2019.Object
      ES2019.String
      ES2019.Symbol
      ES2020.String
      ES2020.Symbol.wellknown
      ES2021.Promise
      ES2021.String
      ES2021.WeakRef
      ESNext.AsyncIterable
      ESNext.Array
      ESNext.Intl
      ESNext.Symbol

      此列表可能已过时,你可以在 TypeScript 源代码中查看完整列表。

      • 相关:
        • noLib

      • 发布版本:

        2.0

      # 库替换 - libReplacement

      TypeScript 4.5 引入了用自定义文件替换默认 lib 文件的能力。所有内置库文件都会首先尝试从名为 @typescript/lib-* 的包中解析。例如,你可以使用以下 package.json,将 dom 库固定到@types/web 包的特定版本:

      json
      {
      "devDependencies": {
      "@typescript/lib-dom": "npm:@types/web@0.0.199"
      }
      }

      安装后,应当会存在一个名为 @typescript/lib-dom 的包,TypeScript 在查找 lib.dom.d.ts 时会始终在那里查找。

      --libReplacement 标志允许你禁用此行为。如果你没有使用任何 @typescript/lib-* 包,现在就可以用 --libReplacement false 禁用这些包查找。将来 --libReplacement false 可能成为默认值,因此如果你目前依赖这一行为,应考虑用 --libReplacement true 显式启用它。

        # 模块检测 - moduleDetection

        此设置控制 TypeScript 如何判断一个文件是脚本还是模块。

        共有三种选择:

        • "auto"(默认)——TypeScript 不仅会查找 import 和 export 语句,还会在 module 为 nodenext 或 node16 时检查 package.json 中的 "type" 字段是否设为 "module",并在 jsx 为 react-jsx 时检查当前文件是否为 JSX 文件。

        • "legacy"——与 4.6 及更早版本的行为相同,使用 import 和 export 语句判断文件是否为模块。

        • "force"——确保每个非声明文件都被视为模块。

        • 默认值:

          "auto":把带有 imports、exports、import.meta、jsx(配合 jsx: react-jsx)或 esm 格式(配合 module: node16+)的文件视为模块。

        • 允许值:
          • legacy

          • auto

          • force

        • 发布于:

          4.7

        # 无库 - noLib

        禁用任何库文件的自动包含。如果设置此选项,lib 将被忽略。

        TypeScript 无法在没有以下关键原语的接口集的情况下编译任何内容:Array、Boolean、Function、IArguments、Number、Object、RegExp 和 String。如果你使用 noLib,就需要为这些类型包含自己的类型定义。

        • 相关:
          • lib

        • 发布于:

          1.0

        # React 命名空间 - reactNamespace

        请改用 jsxFactory。指定在为 TSX 文件以 react 为目标时,createElement 所调用的对象。

        • 默认值:

          React

        • 发布于:

          1.8

        # 目标 - target

        现代浏览器支持所有 ES6 特性,因此 ES6 是个不错的选择。如果你的代码部署到较旧的环境,可以选择较低的目标;如果代码保证在较新的环境中运行,可以选择较高的目标。

        target 设置会改变哪些 JS 特性被降级、哪些保持不变。例如,如果 target 为 ES5 或更低,箭头函数 () => this 会被转换为等价的 function 表达式。

        更改 target 也会改变 lib 的默认值。你可以按需“混搭” target 和 lib 设置,不过为方便起见,只设置 target 也可以。

        对于 Node 之类的开发者平台,target 存在基准值,具体取决于平台类型及其版本。你可以在 tsconfig/bases 找到一组社区维护的 TSConfig,其中包含常见平台及其版本对应的配置。

        特殊的 ESNext 值指的是你的 TypeScript 版本所支持的最高版本。应谨慎使用此设置,因为它在不同 TypeScript 版本之间含义不同,会使升级的可预测性降低。

        • 默认值:

          es2023,前提是 module 为 node20;esnext,前提是 module 为 nodenext;否则为 ES5。

        • 允许值:
          • es3

          • es5

          • es6/es2015

          • es2016

          • es2017

          • es2018

          • es2019

          • es2020

          • es2021

          • es2022

          • es2023

          • es2024

          • es2025

          • esnext

        • 发布于:

          1.0

        # 类字段使用 define 定义 - useDefineForClassFields

        此标志用于迁移到即将成为标准版本的类字段。TypeScript 在 TC39 批准类字段之前很多年就引入了它。即将发布的规范的最新版本与 TypeScript 的实现有着不同的运行时行为,但语法相同。

        此标志会切换到即将发布的 ECMA 运行时行为。

        你可以在 3.7 发行说明中了解更多关于这一过渡的信息。

        • 默认值:

          true,前提是 target 为 ES2022 或更高(包括 ESNext);否则为 false。

        • 发布于:

          3.7

        #编译器诊断

        # 诊断 - diagnostics

        用于输出诊断信息以进行调试。此命令是 extendedDiagnostics 的子集,后者的结果更面向用户,也更易于解读。

        如果有 TypeScript 编译器工程师要求你在一次编译中使用此标志提供结果,那么改用 extendedDiagnostics 也无妨。

        • 已弃用
        • 相关:
          • extendedDiagnostics

        • 发布于:

          1.0

        # 解释文件 - explainFiles

        打印 TypeScript 视为项目组成部分的文件名,以及它们成为编译一部分的原因。

        例如,对于这个仅包含单个 index.ts 文件的项目

        sh
        example
        ├── index.ts
        ├── package.json
        └── tsconfig.json

        使用将 explainFiles 设为 true 的 tsconfig.json:

        json
        {
        "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "explainFiles": true
        }
        }

        对此文件夹运行 TypeScript 会得到类似如下的输出:

        ❯ tsc
        node_modules/typescript/lib/lib.d.ts
        Default library for target 'es5'
        node_modules/typescript/lib/lib.es5.d.ts
        Library referenced via 'es5' from file 'node_modules/typescript/lib/lib.d.ts'
        node_modules/typescript/lib/lib.dom.d.ts
        Library referenced via 'dom' from file 'node_modules/typescript/lib/lib.d.ts'
        node_modules/typescript/lib/lib.webworker.importscripts.d.ts
        Library referenced via 'webworker.importscripts' from
        file 'node_modules/typescript/lib/lib.d.ts'
        node_modules/typescript/lib/lib.scripthost.d.ts
        Library referenced via 'scripthost'
        from file 'node_modules/typescript/lib/lib.d.ts'
        index.ts
        Matched by include pattern '**/*' in 'tsconfig.json'

        上面的输出显示了:

        • 基于 target 的初始 lib.d.ts 查找,以及被引用的 .d.ts 文件链
        • 通过 include 的默认模式找到的 index.ts 文件

        此选项旨在调试某个文件是如何成为编译一部分的。

        • 发布于:

          4.2

        # 扩展诊断 - extendedDiagnostics

        你可以使用此标志来查明 TypeScript 在编译时将时间花在哪里。这是一个用于了解代码库整体性能特征的工具。

        你可以在 wiki 的性能部分中了解更多关于如何衡量和理解输出结果的信息。

        • 相关:
          • diagnostics

        • 发布版本:

          2.0

        # 生成 CPU 配置文件 - generateCpuProfile

        此选项让你有机会让 TypeScript 在编译器运行期间输出一份 v8 CPU 配置文件。该 CPU 配置文件可以深入揭示你的构建为何可能缓慢。

        此选项只能通过 CLI 使用:--generateCpuProfile tsc-output.cpuprofile。

        sh
        npm run tsc --generateCpuProfile tsc-output.cpuprofile

        该文件可以在基于 Chromium 的浏览器(如 Chrome 或 Edge)的开发者工具中,通过在 CPU 性能分析器部分打开。你可以在 TypeScript wiki 的性能部分了解更多关于理解编译器性能的内容。

        • 默认值:

          profile.cpuprofile

        • 发布版本:

          3.7

        # 生成追踪 - generateTrace

        生成事件追踪和类型列表。
        • 发布版本:

          4.1

        # 列出生成的文件 - listEmittedFiles

        将编译中生成的文件名打印到终端。

        此标志在两种情况下很有用:

        • 你希望将 TypeScript 转译作为终端中构建链的一部分,并在下一条命令中处理这些文件名。
        • 作为调试文件包含设置的一部分,你不确定 TypeScript 是否包含了你期望的文件。

        例如:

        example
        ├── index.ts
        ├── package.json
        └── tsconfig.json

        使用:

        {
        "": true,
        }
        }

        会输出类似这样的路径:

        $ npm run tsc
        path/to/example/index.js
        path/to/example/index.d.ts

        通常情况下,TypeScript 在成功时会静默返回。

        • 发布版本:

          2.0

        # 列出文件 - listFiles

        打印参与编译的文件名。当你不确定 TypeScript 是否包含了你期望的文件时,这会很有用。

        例如:

        example
        ├── index.ts
        ├── package.json
        └── tsconfig.json

        使用:

        {
        "": true
        }
        }

        会输出类似这样的路径:

        $ npm run tsc
        path/to/example/node_modules/typescript/lib/lib.d.ts
        path/to/example/node_modules/typescript/lib/lib.es5.d.ts
        path/to/example/node_modules/typescript/lib/lib.dom.d.ts
        path/to/example/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
        path/to/example/node_modules/typescript/lib/lib.scripthost.d.ts
        path/to/example/index.ts

        注意:如果使用 TypeScript 4.2,建议优先使用 explainFiles,它还会解释文件被添加的原因。

        • 相关:
          • explainFiles

        • 发布版本:

          1.5

        # noCheck - noCheck

        禁用完整的类型检查(只会报告关键的解析错误和输出错误)。
        • 发布版本:

          5.6

        # 追踪解析 - traceResolution

        当你想调试某个模块为何未被包含时。你可以将 traceResolution 设为 true,让 TypeScript 打印每个已处理文件的模块解析过程信息。

        • 发布版本:

          2.0

        #项目

        # 复合项目 - composite

        composite 选项会强制实施某些约束,这些约束使构建工具(包括在 --build 模式下运行的 TypeScript 本身)能够快速判断某个项目是否已经构建过。

        启用此设置后:

        • 如果未显式设置,rootDir 设置默认为包含 tsconfig.json 文件的目录。

        • 所有实现文件都必须匹配某个 include 模式,或列在 files 数组中。如果违反此约束,tsc 会告知你哪些文件未被指定。

        • declaration 默认为 true

        你可以在手册中找到关于 TypeScript 项目的文档。

        • 相关:
          • incremental

          • tsBuildInfoFile

        • 发布版本:

          3.0

        # 禁用引用项目加载 - disableReferencedProjectLoad

        在多项目 TypeScript 程序中,TypeScript 会将所有可用的项目加载到内存中,以便为需要完整知识图谱的编辑器响应(如“查找所有引用”)提供准确的结果。

        如果你的项目很大,可以使用 disableReferencedProjectLoad 标志禁用所有项目的自动加载。此时,项目会在你通过编辑器打开文件时动态加载。

        • 发布版本:

          4.0

        # 禁用解决方案搜索 - disableSolutionSearching

        在使用复合 TypeScript 项目时,此选项提供了一种方式,用于声明你不希望在编辑器的查找所有引用或跳转到定义等功能中包含某个项目。

        在大规模复合项目中,你可以使用此标志来提升响应速度。

        • 发布版本:

          3.8

        # 禁用源项目引用重定向 - disableSourceOfProjectReferenceRedirect

        在使用复合 TypeScript 项目时,此选项提供了一种方式,可以回到3.7 之前的行为,即用 d.ts 文件作为模块之间的边界。在 3.7 中,事实来源变成了你的 TypeScript 文件。

        • 发布版本:

          3.7

        # 增量编译 - incremental

        让 TypeScript 将上次编译的项目图信息保存到磁盘上的文件中。这会在编译输出所在的同一文件夹中创建一系列 .tsbuildinfo 文件。它们在运行时不会被你的 JavaScript 使用,可以安全删除。你可以在 3.4 发行说明中进一步了解该标志。

        要控制这些文件构建到哪些文件夹,请使用配置选项 tsBuildInfoFile。

        • 默认值:

          如果启用 composite 则为 true;否则为 false。

        • 相关:
          • composite

          • tsBuildInfoFile

        • 发布版本:

          3.4

        # TS 构建信息文件 - tsBuildInfoFile

        此设置让你指定一个文件来存储增量编译信息,作为复合项目的一部分,从而更快地构建更大的 TypeScript 代码库。你可以在手册中进一步了解复合项目。

        默认值取决于其他设置的组合:

        • 如果设置了 outFile,默认值为 <outFile>.tsbuildinfo。
        • 如果同时设置了 rootDir 和 outDir,那么文件为 <outDir>/<relative path to config from rootDir>/<config name>.tsbuildinfo。例如,如果 rootDir 是 src,outDir 是 dest,配置是 ./tsconfig.json,那么由于从 src/ 到 ./tsconfig.json 的相对路径是 ../,默认值就是 ./tsconfig.tsbuildinfo。
        • 如果设置了 outDir,默认值为 <outDir>/<config name>.tsbuildInfo
        • 否则,默认值为 <config name>.tsbuildInfo
        • 默认值:

          .tsbuildinfo

        • 相关:
          • incremental

          • composite

        • 发布版本:

          3.4

        #输出格式

        # 不截断错误信息 - noErrorTruncation

        不要截断错误消息。

        使用 false(默认)时。

        ts
        var x: {
        propertyWithAnExceedinglyLongName1: string;
        propertyWithAnExceedinglyLongName2: string;
        propertyWithAnExceedinglyLongName3: string;
        propertyWithAnExceedinglyLongName4: string;
        propertyWithAnExceedinglyLongName5: string;
        propertyWithAnExceedinglyLongName6: string;
        propertyWithAnExceedinglyLongName7: string;
        propertyWithAnExceedinglyLongName8: string;
        };
         
        // String representation of type of 'x' should be truncated in error message
        var s: string = x;
        Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propert...' is not assignable to type 'string'.
        Variable 'x' is used before being assigned.
        2322
        2454
        Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propert...' is not assignable to type 'string'.
        Variable 'x' is used before being assigned.
        Try

        使用 true 时

        ts
        var x: {
        propertyWithAnExceedinglyLongName1: string;
        propertyWithAnExceedinglyLongName2: string;
        propertyWithAnExceedinglyLongName3: string;
        propertyWithAnExceedinglyLongName4: string;
        propertyWithAnExceedinglyLongName5: string;
        propertyWithAnExceedinglyLongName6: string;
        propertyWithAnExceedinglyLongName7: string;
        propertyWithAnExceedinglyLongName8: string;
        };
         
        // String representation of type of 'x' should be truncated in error message
        var s: string = x;
        Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; }' is not assignable to type 'string'.
        Variable 'x' is used before being assigned.
        2322
        2454
        Type '{ propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; }' is not assignable to type 'string'.
        Variable 'x' is used before being assigned.
        Try
        • 发布版本:

          1.0

        # 保留监视输出 - preserveWatchOutput

        在监视模式下是保留过时的控制台输出,还是每次发生更改时清屏。

        • 内部
        • 发布版本:

          2.8

        # 美化 - pretty

        使用颜色和上下文美化错误和消息,默认开启——让你有机会获得编译器给出的不那么简略的单色消息。

        • 默认值:

          true

        • 发布版本:

          1.8

        #完整性

        # 跳过默认库检查 - skipDefaultLibCheck

        请改用 skipLibCheck。跳过对默认库声明文件的类型检查。

        • 发布版本:

          1.6

        # 跳过库检查 - skipLibCheck

        跳过声明文件的类型检查。

        这可以节省编译时间,但会牺牲类型系统的准确性。例如,两个库可能以不一致的方式定义同一个 type 的两份副本。TypeScript 不会对所有 d.ts 文件进行完整检查,而是对你应用中源代码明确引用的代码进行类型检查。

        你可能想使用 skipLibCheck 的常见情况是:node_modules 中存在某个库类型的两份副本。在这些情况下,你应该考虑使用 yarn 的 resolutions 之类的功能,以确保依赖树中只有一份该依赖,或者通过理解依赖解析来研究如何确保只有一份副本,从而在不借助额外工具的情况下解决问题。

        另一种情况是:在 TypeScript 版本之间迁移时,这些更改导致 node_modules 和 JS 标准库中出现破坏,而你不希望在 TypeScript 更新期间处理这些问题。

        注意,如果这些问题来自 TypeScript 标准库,你可以使用 TypeScript 4.5 的库替换技术来替换该库。

        • 推荐
        • 发布版本:

          2.0

        #命令行

        #监视选项

        TypeScript 3.8 提供了新的目录监视策略,这对于高效感知 node_modules 的变化至关重要。

        在 Linux 等操作系统上,TypeScript 会在 node_modules 及其许多子目录上安装目录监视器(而不是文件监视器)来检测依赖变化。这是因为可用文件监视器的数量往往被 node_modules 中的文件数量所淹没,而要跟踪的目录却少得多。

        由于每个项目可能在不同策略下表现更好,而且这种新方式可能不适合你的工作流,TypeScript 3.8 引入了新的 watchOptions 字段,让用户可以告诉编译器/语言服务应使用哪些监视策略来跟踪文件和目录。

        # 假设更改仅影响直接依赖 - assumeChangesOnlyAffectDirectDependencies

        启用此选项后,TypeScript 将避免重新检查/重建所有真正可能受影响的文件,而只重新检查/重建已更改的文件以及直接导入它们的文件。

        这可以看作监视算法的一种“快速而宽松”的实现,它能大幅缩短增量重建时间,代价是偶尔需要运行完整构建才能获得所有编译器错误消息。

        • 发布:

          3.8

        监视选项

        你可以配置 TypeScript --watch 的工作方式。本节主要处理 fs.watch 和 fs.watchFile 在 Linux 等平台上具有额外限制的情况。你可以在配置监视中阅读更多内容。

        # 监视文件 - watchFile

        监视单个文件所采用的策略。

        • fixedPollingInterval:以固定间隔每秒多次检查每个文件是否有更改。
        • priorityPollingInterval:每秒多次检查每个文件是否有更改,但使用启发式规则,以低于其他文件的频率检查某些类型的文件。
        • dynamicPriorityPolling:使用动态队列,修改频率较低的文件将被检查得更少。
        • useFsEvents(默认):尝试使用操作系统/文件系统的原生事件来监听文件更改。
        • useFsEventsOnParentDirectory:尝试使用操作系统/文件系统的原生事件来监听文件父目录的更改
        • 允许值:
          • fixedpollinginterval

          • prioritypollinginterval

          • dynamicprioritypolling

          • fixedchunksizepolling

          • usefsevents

          • usefseventsonparentdirectory

        • 发布:

          3.8

        # 监视目录 - watchDirectory

        在不支持递归文件监视的系统上,监视整个目录树所采用的策略。

        • fixedPollingInterval:以固定间隔每秒多次检查每个目录是否有更改。
        • dynamicPriorityPolling:使用动态队列,修改频率较低的目录将被检查得更少。
        • useFsEvents(默认):尝试使用操作系统/文件系统的原生事件来监听目录更改。
        • 允许值:
          • usefsevents

          • fixedpollinginterval

          • dynamicprioritypolling

          • fixedchunksizepolling

        • 发布:

          3.8

        # 回退轮询 - fallbackPolling

        在使用文件系统事件时,此选项指定当系统耗尽原生文件监视器或(和)不支持原生文件监视器时所采用的轮询策略。

        • fixedPollingInterval:以固定间隔每秒多次检查每个文件是否有更改。
        • priorityPollingInterval:每秒多次检查每个文件是否有更改,但使用启发式规则,以低于其他文件的频率检查某些类型的文件。
        • dynamicPriorityPolling:使用动态队列,修改频率较低的文件将被检查得更少。
        • synchronousWatchDirectory:禁用目录上的延迟监视。当可能同时发生大量文件更改时(例如运行 npm install 导致 node_modules 发生变化),延迟监视很有用,但在某些较少见的配置下,你可能想用此标志将其禁用。
        • 允许值:
          • fixedinterval

          • priorityinterval

          • dynamicpriority

          • fixedchunksize

        • 发布:

          3.8

        # 同步监视目录 - synchronousWatchDirectory

        在原生不支持递归监视的平台上,同步调用回调并更新目录监视器的状态,而不是设置一个短暂的超时来等待文件上可能发生的多次编辑。

        {
        "watchOptions": {
        }
        }
        • 发布:

          3.8

        # 排除目录 - excludeDirectories

        你可以使用 excludeFiles 大幅减少 --watch 期间监视的文件数量。这是在 Linux 上减少 TypeScript 跟踪的打开文件数的有用方式。

        {
        "watchOptions": {
        "": ["**/node_modules", "_build", "temp/*"]
        }
        }
        • 发布:

          4.2

        # 排除文件 - excludeFiles

        你可以使用 excludeFiles 从被监视的文件中移除一组特定文件。

        {
        "watchOptions": {
        "": ["temp/file.ts"]
        }
        }
        • 发布:

          4.2

        类型获取

        类型获取只对 JavaScript 项目重要。在 TypeScript 项目中,你需要显式地在项目中包含类型。不过,对于 JavaScript 项目,TypeScript 工具会在后台下载模块的类型,并将其放在 node_modules 文件夹之外。

        # 启用 - enable

        在 JavaScript 项目中禁用自动类型获取:

        json
        {
        "typeAcquisition": {
        "enable": false
        }
        }

          # 包含 - include

          如果你的 JavaScript 项目中 TypeScript 需要额外指引才能理解全局依赖,或者你通过 disableFilenameBasedTypeAcquisition 禁用了内置推断。

          你可以使用 include 指定应使用 DefinitelyTyped 中的哪些类型:

          json
          {
          "typeAcquisition": {
          "include": ["jquery"]
          }
          }

          # 排除 - exclude

          提供一个配置,用于在 JavaScript 项目中禁用某个模块的类型获取。对于在测试基础设施中包含其他库、而主应用并不需要这些库的项目,这会很有用。

          json
          {
          "typeAcquisition": {
          "exclude": ["jest", "mocha"]
          }
          }

          # 禁用基于文件名的类型获取 - disableFilenameBasedTypeAcquisition

          TypeScript 的类型获取可以根据项目中的文件名推断应添加哪些类型。这意味着项目中若有像 jquery.js 这样的文件,就会自动从 DefinitelyTyped 下载 jQuery 的类型。

          你可以通过 disableFilenameBasedTypeAcquisition 禁用此行为。

          json
          {
          "typeAcquisition": {
          "disableFilenameBasedTypeAcquisition": true
          }
          }
          • 发布时间:

            4.1