我在使用 Typescript 和导入moment
包时遇到了一个奇怪的问题。我在几个不同的地方看到过它,我什至看到它出现在同一个文件中,这取决于我是否向类添加了特定的静态方法。
问题是这样的:
当我使用 导入 moment 时import * as moment from 'moment';
,我没有遇到 Typescript 错误,但是我的测试确实遇到了问题;具体来说,他们失败了TypeError: moment is not a function
。
当我更改导入时import moment from 'moment';
,代码有效,但我得到"moment" has no default export
.
我不明白这些之间的区别。我已经看到了其他问题(比如这个,它推荐了第一种语法)。对上述问题的已接受答案的评论建议打开allowSyntheticDefaultImports
标志,这确实纠正了问题,但我有点担心该标志。文档说:
允许从没有默认导出的模块中默认导入。这不会影响代码发出,只是类型检查。
这似乎意味着没有对以这种方式导入的模块进行类型检查。
所以,两个问题:
allowSyntheticDefaultImports
是否正确理解了该标志的 TS 文档?它是否关闭了moment
包的类型检查?FWIW,我正在使用 Typescript 3.4.5 和时刻 2.24.0。
allowSyntheticDefaultImports
,这不是你想要的。你要esModuleInterop
。TL; DR开启esModuleInterop
和更换的每个实例import * as foo from 'foo'
有import foo from 'foo'
。
问题源于 Noderequire
过于灵活。您几乎可以导出任何内容。由于超出本问题范围的原因,这使得优化生成的代码变得非常困难。
当 ES 定义模块时,他们定义了一些稍微结构化的东西。您必须导出一个普通对象。这个对象可以有一个命名的属性,default
但它不需要。
不幸的是,许多 JS 包没有遵循这个约定。如果我们看moment
...
> const moment = require('moment');
undefined
> typeof moment
'function'
> moment.default
undefined
Run Code Online (Sandbox Code Playgroud)
您可以看到moment
导出了一个函数,它没有名为default
. 对于 TS 来说,这是一个难题,它旨在坚持 ES 标准,但又希望支持导入不符合标准的老式模块。
如果您要编译到较旧的目标并替换import * as foo from 'foo'
为const foo = require('foo');
. 想法是没有人真正需要import * as foo from 'foo'
,所以这是一种劫持导入样式以支持旧模块的方法。但是它不符合 ES6,因为 的返回值import * as foo from 'foo'
应该始终是一个对象,如果我们将其替换为 ,require
那么我们可能不会得到一个对象。
不幸的是,这会导致您的代码根据您的目标和构建方式的不同而表现不同。如果您以 ES5 为目标,那么它将回require
退到该行为,您将返回一个function
. 如果你以 ES6 为目标(这在使用某种打包器时经常发生),那么它会被放入import * as foo from 'foo'
并且打包器可能会以不同的方式解释它。他们通常做的是为您提供一个对象,该对象具有default
设置为该函数的单个属性。
因此,解决方案是劫持import moment from 'moment'
语法。在 ES6 中,它的作用是导入default
导出的任何内容的属性。好消息是,这意味着被导入的东西不必是一个对象,也可以是一个函数。因此,与其只是加入const moment = require('moment')
TS ,不如做一些不同的事情。它创建一个具有单个属性的对象,default
并将其设置为等于require('moment')
,然后返回该属性。
这实际上只是解决相同问题的不同技巧,但它遵循 ES6 规范,并且其行为与 Babel 的行为方式更相似。或者,引用有关此功能的TS 发行说明:
注意:新行为添加在一个标志下,以避免对现有代码库造成不必要的破坏。我们强烈建议将其应用于新项目和现有项目。对于现有项目,命名空间导入(import * as express from "express"; express();)需要转换为默认导入(import express from "express"; express();)。
归档时间: |
|
查看次数: |
3223 次 |
最近记录: |