编译器配置项-compilerOptions
操作约束相关配置项03
保留符号链接 - preserveSymlinks
这个配置选项是为了反映 Node.js 中的相同配置选项,它不会解析符号链接的实际路径。
这个配置项还表现出与 Webpack 的 resolve.symlinks
选项相反的行为(即,将 TypeScript 的 preserveSymlinks
设置为true
相当于将 Webpack 的 resolve.symlinks
设置为 false,反之亦然)。
启用词功能后,对模块和包的引用(例如imports
和 /// <reference type="..." />
指令)均为相对于符号链接文件的位置进行解析,而不是相对于符号链接文件指向的文件的路径。
逐字模块语法 - verbatimModuleSyntax
默认情况下,TypeScript 会执行称为导入省略的操作。基本上,如果你写类似的代码:
import { Car } from "./car";
export function drive(car: Car) {
// ...
}
TypeScript 检测到你仅使用了导入的类型,那么将删除全部的导入语句,输出的 JavaScript 可能如下所示:
export function drive(car) {
// ...
}
大多数情况下,这都是正常的,因为如果 Car
不是从 ./car
导出,我们将会收到运行时错误。
但它确实为某些少数场景增加了一层复杂性。假如,没有像 import "./car";
这样的语句 ,即导入语句被完全删除。这实际上对不同的模块会产生不同的影响:产生副作用或者没有。
TypeScript 输出 JavaScript 的策略还有另外几层复杂性 - 导入省略并不总是由导入的使用方式驱动 - 它通常还会参考值的声明方式。因此,对于像下面这样的代码并不总是清楚的:
export { Car } from "./car";
这种情况应该保留import
语句,还是删除呢?如果 Car
声明为类似class
的内容,则可以将其保留在生成的 JavaScript 文件中。但是如果 Car
仅声明为type
或 interface
, 那么 JavaScript 文件中根本不应该保留导出的 Car
。
虽然 TypeScript 可能能够根据不同的文件的信息做出决定:如何输出import
,但并非每个编译器都可以。
type
修饰符将对这种的情况下的导入和导出有些帮助。这样我们可以明确导入或导出的内容是否仅用于类型分析,并且可以在JavaScript文件中完全如果使用了 type
修饰符。
type
修饰符本身并不是很有用,默认情况下,模块省略仍会删除imports
,并且不会强制你去区分导入和导出的是 type
还是普通值。因此,TypeScript 使用 importsNotUsedAsValues
配置项来确保你使用 type
修饰符,使用preserveValueImports
配置项防止某些模块省略行为,isolatedModules
配置项来确保 TypeScript 代码可以在不同的编译器上运行。但是不幸的是,理解这 3 个配置项的细节很难,并且仍然有一些超出期望行为的极端情况。
TypeScript 5.0 引入了一个名为 verbatimModuleSyntax
的新选项来简化这种情况。它规则要简单得多,任何没有 type
修饰符的导入或导出都会被保留,任何使用 type
修饰符的内容都会被完全删除。
// 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 imports
和 exports
不会被重写为 require
,相反,会收到错误。如果你需要输出使用 require
和 module.exports
的代码,则必须使用早于 ES2015 的 TypeScript 模块语法,下边的TypeScript代码:
// example1
import foo = require("foo");
// example2
function foo() {}
function bar() {}
function baz() {}
export = {
foo,
bar,
baz,
};
输出的JavaScript代码如下:
// example1 output
const foo = require("foo");
// example2 output
function foo() {}
function bar() {}
function baz() {}
module.exports = {
foo,
bar,
baz,
};
虽然选项有这样的限制,但它确实有助于使一些问题更加明显。例如,忘记在 module
配置为node16
工程的 package.json
中设置 type
字段是很常见的。因此,开发人员会在不知不觉中开始编写 CommonJS 模块而不是 ES 模块,该选项将会给出令人惊讶建议和 JavaScript 输出。这个新选项可以确保你注意使用的文件类型,因为不同的文件类型语法是不同的。
因为 verbatimModuleSyntax
选项比 importsNotUsedAsValues
和 preserveValueImports
两个选项提供更好的一致性,所以这两个现有标志被弃用。
网友评论