Skip to content
目录

emitDecoratorMetadata - 👍 生成装饰器元数据

启用对使用reflect-metadata模块的装饰器生成类型元数据的实验性支持。

比如,🌰 ts:

typescript
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()

不开启 emitDecoratorMetadata(默认值),生成的JS如下:

js
"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();

开启 emitDecoratorMetadata,生成的JS如下:

js
"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();

💡

相关联配置:

experimentalDecorators

开启 对装饰器实验性的支持,它处于TC39标准化过程中的第2阶段。

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

decorators - handbook 中可以找到更多TS对装饰器支持的内容。

💡

相关联配置:

JSX 👍🚀

控制JSX构造在JS文件中如何生成。这只会对 .tsx 文件输出生成的JS文件有影响。

  • react:生成 .js 文件,JSX 转换为等价的 React.createElement 方法调用
  • react-jsx:生成 .js 文件,JSX 转换为 _jsx 调用 😎
  • react-jsxdev:生成 .js 文件,JSX 转换为 _jsx 调用
  • preserve: 生成 .jsx 文件,JSX 语法保持不变
  • react-native:生成 .js 文件,JSX 语法不变

例子:

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

1️⃣ 默认是 "react"

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

2️⃣ "preserve"

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

3️⃣ RN中 react-native

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

4️⃣ React 17 转换:react-jsx

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

5️⃣ React 17 开发转换:react-jsxdev

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

💡

可能值:

  • preserve
  • react
  • react-native
  • react-jsx
  • react-jsxdev

相关联配置:

jsxFactory - preact

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

例子,tsx:

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

开启 jsxFactory: "h" 看起来如下:

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

这个选项可以在每个文件的基础上使用,类似于 Babel的 /** @jsx h */ 指令

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

所选择的工厂还将影响在返回到全局名称空间之前查找 JSX 名称空间的位置(用于类型检查信息)。

👩‍🏫 如果功能被定义为 React.createElement (默认),编译器将在检查全局 JSX 之前检查 React.JSX。如果工厂被定义为 h,它将检查全局 JSX 之前检查 h.JSX

💡

默认:React.createElement

可能值: 任意标识符或点标识符

相关联配置:

jsxFragmentFactory

当目标是React JSX,并使用 jsxFactory 编译器选项时,指定 JSX Fragment 工厂函数,比如 Fragment

比如下面 tsconfig.json

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment"
  }
}

下面 tsx 文件:

tsx
import { h, Fragment } from 'preact'

const HelloWorld = () => (
  <>
    <div>Hello</div>
  </>
)

编译产物:

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

这个配置项可以用作每个文件的基础,类似于 Babel的 /* @jsxFrag h */ 指令

比如:

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

💡

默认值:React.Fragment

相关联配置:

jsxImportSource

当使用jsx作为"react-jsx""react-jsxdev"时,声明用于导入jsxjsxs工厂函数的模块说明符,这些在TypeScript 4.1中引入。

使用 React 17 库通过单独的导入支持一种新的JSX转换形式。

1️⃣ 比如:

tsx
import React from 'react'

function App() {
  return <h1>Hello World</h1>
}

使用下面 tsconfig.json

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react-jsx"
  }
}

生成的js文件:

js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
function App() {
    return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
}

2️⃣ 比如,你想使用 "jsxImportSource": "preact",则需要使用下面 tsconfig.json

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    "types": ["preact"]
  }
}

生成代码如下:

js
function App() {
    return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
}
exports.App = App;

另外,你可以使用每个文件的pragma来设置此选项,比如:

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

该pragma将添加 preact/jsx-runtime 作为对 _jsx 工厂的导入。

🚨: 为了如你预期的那样工作,你的 tsx 文件必须包含一个 exportimport,这样它才会被当做为一个模块。

TIP

默认值:react

相关联配置:

lib 👍🚀

TS对内置的JS APIs(比如 Math)包含一组默认的类型定义,也提供了对浏览器环境(比如 document) 的类型定义😎。TS也包含新的JS APIs功能,以匹配你指定的 target;比如,对 Map 的定义只在 targetES6 以上才能访问。

🤔 你可能基于以下几个原因去改变这个配置:

  • 你的程序不是运行在浏览器中,因此你不想要 dom 类型定义
  • 你的运行时平台提供了特定的JS API对象(可能通过 polyfills),但是没有对给定ECMAScript版本提供完整的语法支持
  • 存在对高阶的ECMAScript版本提供了一些但是不全的polyfills或原生实现。

在TS4.5中,lib文件可以被npm modules覆写,supporting lib from node_modules

🚀 高阶库:

名称内容
ES5所有ES3 & ES5功能核心定义
ES2015ES6中额外的APIs - array.find, Promise, Proxy, Symbol, Map, Set, Reflect
ES6ES2015 的别名
ES2016arry.include
ES7ES2016 的别名
ES2017Object.entries, Object.values, Atomics, SharedArrayBuffer, date.formatToParts, TypeArray
ES2018async iterables, promise.finally, Intl.PluralRules, regexp.groups
ES2019array.flat, array.flatMap, Object.fromEntries, string.trimStart, string.trimEnd
ES2020string.matchAll
ES2021promise.any, string.replaceAll
ESNext跟着最新JS规范变化
DOMDOM 定义 - window, document
WebWorkerWebWorker 上下文APIs
ScriptHostWindows Script Hosting System APIs

🚀 单独的库组件:

  • DOM.Iterable
  • ES2015.Core, ES2015.Collection, ES2015.Generator, ES2015.Iterable, ES2015.Promise, ES2015.Porxy, ES2015.Reflect, ES2015.Symbol, ES2015.Symbol.WellKnown
  • ES2016.Array.Include
  • ES2017.object, ES2017.Intl, 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.wellknow
  • ES2021.Promise, ES2021.String, ES2021.Weakref
  • ESNext.AsyncIterable, ESNext.Array, ESNext.Intl, ESNext.Symbol

这个列表可能会过期,可通过 TS源码 查看完整列表。

moduleDetection

有3个选项:

  • "auto": TS不仅查看导入和导出语句,当运行 modulenodenext | node16时, 同时也会查看 package.josn 中的 "type" 属性是否设置为了 "module",并且在 jsx: "react-jsx" 时检查当前文件是否是一个 JSX 文件。
  • "legacy": 这个行为通TS4.6和之前版本,使用导入和导出语句决定文件是否是一个模块
  • "force": 确保每个非声明文件都被当做为一个模块

💡

默认值:"auto" - 把含有 imports | exports | import.meta | jsx(使用 react-jsxjsx) | ems(使用 module: node16+) 格式的文件当做是模块

可能值:

  • allow
  • auto
  • force

noLib 👍

禁用自动包含任何库文件。

WARNING

如果设置了这个值, lib 配置将被忽略。

如果没有一组关键原始类型的接口,TypeScript无法编译任何东西,比如:Array、Boolean、Function、IArguments、Number、Object、RegExp和String。如果你使用noLib,你应该包含你自己的类型定义。

💡

相关联配置:

reactNamspace

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

💡

默认值: React

target 👍🚀🚀

现代浏览器支持所有ES6功能,因此 ES6 是一个好的选择😎。如果你的代码部署在较老的环境,则可以使用更低版本目标;如果在更新的环境,则可以使用更高版本的目标。

target 设置改变了哪些JS特性被降级,哪些保持原样。比如,如果 targetES6 或更低版本,箭头函数 () => this 将会转换为等价的 function 表达式。

改变 target 也会改变 lib 的默认值。如果你愿意,你也可以混合和匹配 target & lib,但是为了方便,你可以只设置 target😎。

🚀🚀 对于Node这种开发者平台,取决于平台和其版本,target 存在底线。你可以在 tsconfig/bases 找到一些社区组织的TSConfigs,上面存在一些通用平台及其版本的通用配置。

特别的 ESNext 值指TS所支持的最高版本。应当谨慎使用这个值,因为它意味着,不同版本的TS支持的东西可能是不一样的,这使得升级变得不可预测。

💡

默认值: ES3

可能值:

  • es3
  • es6/es2015
  • es2016
  • es2017
  • es2018
  • es2019
  • es2020
  • es2021
  • es2022
  • esnext

useDefineForClassFields

该标志用于迁移到即将到来的类字段标准版本。

TypeScript在TC39认可类字段之前很多年就引入了类字段。即将发布的最新版本的规范与TypeScript的实现有不同的运行时行为,但语法相同。

这个标志会切换到即将到来的ECMA运行时行为。

你可以阅读 TS3.7 发布注意事项 了解更多。

💡

默认值:

  • 如果 targetES2022 或 更高版本,包括 ESNext,则默认是 true;否则为 false

2022年08月21日21:06:53