Bug报告
preserveValueImports
在导入带有 isolatedModules
on 的 ambient const enum 时不会报错。相反,你会在运行时得到一个错误。
🩹 建议解决方案
如果命名导入是类型而不是 ambient const enum,你会得到编译时错误。
#47817 通过将其 predicate 更改为包括 ambient const enums 来引发该错误。
🔍 搜索关键词
preserveValueImports
ambient const enum
🕗 版本与回归信息
4.5.0-dev.20210909 - 4.7.0-dev.20220225
⏯️ Playground 链接
Workbench Repro
🧑💻 代码
// @preserveValueImports
// @isolatedModules
import { RoundingMode } from "big.js";
// @filename: node_modules/big.js/index.d.ts
export const enum RoundingMode {}
🙁 实际行为
运行时错误:
import { RoundingMode } from "big.js";
^^^^^^^^^^^^
SyntaxError: Named export 'RoundingMode' not found. The requested module 'big.js' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'big.js';
const { RoundingMode } = pkg;
🙂 预期行为
编译时错误(使用 #47817):
index.ts:1:10 - error TS1446: 'RoundingMode' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled.
1 import { RoundingMode } from "big.js";
~~~~~~~~~~~~
5条答案
按热度按时间1dkrff031#
@andrewbranch what's your take? The linked PR has some additional context
bis0qfac2#
我认为在ambient上的区分是非常有问题的,尽管我理解为什么这样做是诱人的。如果我们不是在讨论const enums的谜题,那么将ambient视为非ambient声明的存在方式是非常错误的。Ambient声明假定与其他非ambient声明一样存在,只是编译器不知道它们的位置。类型检查行为通常不应受到ambient的影响;否则,您将在消费.ts文件和消费相同文件的.d.ts输出之间获得不同的行为。更令人困惑的是,在项目引用中,您将在CLI和编辑器之间获得不同的行为,因为前者使用.d.ts文件引用的项目,而后者默认使用.ts文件。
当谈论const enums时,故事略有不同,因为当您
tsc -d
一个const enum声明时,我们在.d.ts文件中发出一个(ambient)const enum声明,并且是否存在现有的运行时值可以根据其他编译器选项进行切换。因此,给定一个ambient const enum声明,我们真的不知道是否存在一个运行时等效项。(这是我提议为const enums引入某种语法标记以指示是否存在真正的运行时等效项的基础,但被拒绝了,因为它似乎使枚举变得更复杂。我认为这个问题表明这样的标记不会扩展我们关心的枚举信息的位数,而是编码了一个相当基本的问题——是否存在任何运行时表示——我们已经尝试考虑但未能准确地做到这一点。)另一方面,如果编译器看到一个非ambient const enum声明,它可以知道是否存在运行时等效项,因为当前的编译将负责生成它。所以我认为在这里的提案在许多方面是有意义的:实际上是项目引用的情况让我对这个感到不安。在没有其他更改的情况下,您将无法使用
--isolatedModules --preserveValueImports
从引用的项目中消费自己的保留const enums,但这个错误不会出现在编辑器中。我们可以检查声明是否来自项目引用重定向,并检查引用项目的编译器选项(这将需要向TypeCheckerHost
添加另一个API)以查看它是否会被保留。但这也可能不太正确,因为const enum声明可能是在输入文件中用declare
手写的,通过这个复杂的逻辑,我们可以说应该出错(???),因为我们再次不确定是否存在运行时等效项。总结:
brjng4g33#
感谢!
https://github.com/microsoft/TypeScript/blob/e4fe50cca477a3e46f9b629a6c5be0b0ed8b010f/src/compiler/checker.ts#L34251
所以在大多数情况下,你不能从引用的项目中使用
--isolatedModules
消耗自己的保留 const 枚举,而且这个错误不会出现在编辑器中?关于删除 vs. 为保留 const 枚举的声明发出标记的设计会议记录:Design Meeting Notes,12/1/2021 #46983 (评论)
换句话说,这个提案不引入任何新问题吗?对于您提到的现有问题,有一个解决方案可以在 const enums 的声明发出中添加更多信息,但它在内联引用项目的枚举时有问题? ... 但也许可以解决这个问题?这是一个单独的问题吗?
rur96b6h4#
这仍然是
verbatimModuleSyntax
的问题,但我在之前的信息中关心的项目引用差异最近在#57914中得到了处理。我认为我们应该继续为5.6这样做。在导入时出错没有太大意义,但在保留的导入中出错是有意义的。在verbatimModuleSyntax
下,我们应该让错误仅出现在导入处,而不是使用站点。这样,我们可以使用单个ts-ignore来摆脱不知道 ambient const enum 是否与preserveConstEnums
示例化的困境的情况。von4xj4u5#
你好,我是Repro bot。我可以协助缩小范围并跟踪不同版本的编译器错误!此评论反映了问题正文中运行的夜间TypeScript的当前重现状态。
问题正文代码块由@jablko提供
异常:错误 - TS5102错误:选项'preserveValueImports'已被移除。请从您的配置中删除它。请使用'verbatimModuleSyntax'代替。
历史信息
| 版本 | 重现输出 | 时间 |
| ------------ | ------------ | ------------ |
| 5.0.2, 5.1.3, 5.2.2, 5.3.2, 5.4.2 | !!️异常:错误 - TS5101错误:选项'preserveValueImports'已弃用,将在TypeScript 5.5中停止工作。指定编译器选项'ignoreDeprecations': '5.0'以静默此错误。请使用'verbatimModuleSyntax'代替。
| ⚠️速度慢得多 |