【问题标题】:How can moment.js be imported with typescript?moment.js 如何用 typescript 导入?
【发布时间】:2021-06-27 20:10:07
【问题描述】:

我正在尝试学习 Typescript。虽然我认为这无关紧要,但我在此演示中使用 VSCode。

我有一个package.json,里面有这些片段:

{
  "devDependencies": {
    "gulp": "^3.9.1",
    "jspm": "^0.16.33",
    "typescript": "^1.8.10"
  },
  "jspm": {
    "moment": "npm:moment@^2.12.0"
  }
}

然后我有一个 Typescript 类 main.js 像这样:

import moment from 'moment';
export class Main {
}

我的gulpfile.js 看起来像这样:

var gulp = require('gulp');
var typescript = require('gulp-tsb');
var compilerOptions = {
                        "rootDir": "src/",
                        "sourceMap": true,
                        "target": "es5",
                        "module": "amd",
                        "declaration": false,
                        "noImplicitAny": false,
                        "noResolve": true,
                        "removeComments": true,
                        "noLib": false,
                        "emitDecoratorMetadata": true,
                        "experimentalDecorators": true
                      };
var typescriptCompiler = typescript.create(compilerOptions);
gulp.task('build', function() {
  return gulp.src('/src')
    .pipe(typescriptCompiler())
    .pipe(gulp.dest('/dest'));
});

当我运行 gulp build 时,我收到消息:"../main.ts(1,25): Cannot file module 'moment'."

如果我使用import moment = require('moment');,那么 jspm 将在我运行应用程序时工作并引入模块,但我仍然收到构建错误。 我也试过了:

npm install typings -g
typings install moment --ambient --save

问题不但没有改善,反而变得更糟。现在我在构建时收到上述错误以及以下错误:"../typings/browser/ambient/moment/index.d.ts(9,21): Cannot find namespace 'moment'."

如果我转到typings提供的文件并在文件底部添加:

declare module "moment" { export = moment; }

我可以让第二个错误消失,但我仍然需要 require 语句才能在我的 main.ts 文件中工作,并且仍然遇到第一个构建错误。

我需要暂时创建自己的.d.ts 文件还是缺少一些设置?

【问题讨论】:

  • 为现在遇到此问题的任何人添加此更新:import moment, { Moment } from 'moment'; 允许您执行 const x = moment();const x: Moment = moment();
  • 这些解决方案都不起作用,我搬到了这里 - github.com/date-fns/date-fns

标签: typescript momentjs jspm


【解决方案1】:

更新

显然,moment 现在提供了自己的类型定义(根据sivabudh 至少从 2.14.1 开始),因此您根本不需要typings@types

import * as moment from 'moment' 应该加载 npm 包提供的类型定义。

话虽如此,正如moment/pull/3319#issuecomment-263752265 中所说,目前团队似乎在维护这些定义方面存在一些问题(他们仍在寻找维护这些定义的人)


您需要安装不带--ambient 标志的moment 类型。

然后使用import * as moment from 'moment' 包含它

【讨论】:

  • 那行得通。你能解释一下使用--ambient 标志和不使用标志之间的区别吗?我让 numericjs 使用环境标志工作。此外,他们的主页npmjs.com/package/typings 给出了使用环境标志的示例。我不知道我什么时候想要/需要使用其中一个。谢谢!
  • 说实话,我做不到。通常你对来自typings/DefinitelyTyped 的所有Typescript 定义使用--ambient 标志,但是moment 定义有一些奇怪的结构并且文件没有正确下载。如果您查看定义文件moment.d.ts,它仅包含对节点版本的引用,下载时未解决(可能值得打开一个问题)。
  • 显然已经有一个与这个问题有关:github.com/DefinitelyTyped/DefinitelyTyped/issues/8388
  • 我使用 import * as moment from 'moment/moment' b/c 让它工作,它被安装为节点模块文件夹中的子文件夹。
  • 我在 webpack 上,并且时刻版本 2.17.1 但仍然无法使其工作。我试过: import * as moment from 'moment';并从“时刻/时刻”导入*作为时刻;并且不工作!
【解决方案2】:

你需要在TS中分别导入moment()函数和Moment类。

我在打字稿文档here 中找到了一条注释。

/*~注意ES6模块不能直接导出可调用函数
*~ 此文件应使用 CommonJS 样式导入:
*~ import x = require('someLibrary');

所以将 moment js 导入 typescript 的代码实际上是这样的:

import { Moment } from 'moment'
....
let moment = require('moment');
...
interface SomeTime {
  aMoment: Moment,
}
...
fn() {
  ...
  someTime.aMoment = moment(...);
  ...
}

【讨论】:

  • 很好的答案,因为它显示了类型和功能之间的区别。谢谢!
  • 找不到名字'require'
  • 现在可以将其用作import * as moment from 'moment';,然后使用moment.Moment 进行打字。
  • 对我有用的是:import moment = require('moment');
  • 其实你也可以直接从命名空间moment使用moment.Moment接口
【解决方案3】:

不确定何时更改,但使用最新版本的打字稿,您只需要使用import moment from 'moment';,其他一切都应该正常工作。

更新:

看起来最近修复了它们的导入。至少从 2.24.0 开始,您将希望使用 import * as moment from 'moment';

【讨论】:

  • import * as moment from 'moment' 不适用于打字稿,但 import moment from 'moment' 可以。
  • 它正在工作,但我得到的是 GMT 0 的时间,但我需要本地时间,这不起作用我也尝试使用 moment().utc().format() 但它正在恢复相同结果。
  • @kbhaskar 截至他们修复导入的最新版本。查看更新的答案
  • 我觉得差不多了。我必须做的唯一额外步骤是在我的配置中添加esModuleInterop 设置为true,这是我从this answer 获得的。谢谢。
【解决方案4】:

通过打字

Moment.js 现在在 v2.14.1 中支持 TypeScript。

见:https://github.com/moment/moment/pull/3280


直接

可能不是最好的答案,但这是蛮力的方式,它对我有用。

  1. 只需下载实际的moment.js 文件并将其包含在您的项目中即可。
  2. 例如,我的项目如下所示:

$ tree . ├── main.js ├── main.js.map ├── main.ts └── moment.js

  1. 这是一个示例源代码:

```

import * as moment from 'moment';

class HelloWorld {
    public hello(input:string):string {
        if (input === '') {
            return "Hello, World!";
        }
        else {
            return "Hello, " + input + "!";
        }
    }
}

let h = new HelloWorld();
console.log(moment().format('YYYY-MM-DD HH:mm:ss'));
  1. 只需使用node 运行main.js

【讨论】:

  • 是的,我确认这是正确的答案。像魅力一样工作。
  • 当我尝试使用 npm i @types/moment 执行此操作时,我收到一个错误:TypeScript error: src\app.ts(1,1): error TS7038: A namespace-style import cannot被调用或构造,并且会在运行时导致失败。在 tsc -v 2.7.2
【解决方案5】:

我刚刚注意到我赞成和评论的答案是模棱两可的。因此,以下正是对我有用的方法。我目前在 Moment 2.26.0 和 TS 3.8.3

在代码中:

import moment from 'moment';

在 TS 配置中:

{
  "compilerOptions": {
    "esModuleInterop": true,
    ...
  }
}

我正在为两个 CommonJS 和 EMS 构建,所以这个配置被导入到其他配置文件中。

见解来自this answer,它与使用 Express 有关。不过,我认为值得在这里添加,以帮助任何与 Moment.js 相关的搜索,而不是更笼统的内容。

【讨论】:

  • 那么您可以像平常一样使用moment() 而不是moment.default()
【解决方案6】:

还是坏了?尝试卸载@types/moment

所以,我从package.json 文件中删除了@types/moment 包,它使用:

import * as moment from 'moment'

较新版本的moment 不需要@types/moment 包,因为类型已包含在内。

【讨论】:

    【解决方案7】:

    ES6 语法:

    1.安装时刻

    npm install --save moment
    

    2.在您的打字稿文件中导入“时刻”

    import moment from 'moment';
    

    【讨论】:

    猜你喜欢
    • 2016-11-16
    • 2017-06-12
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 2016-05-04
    • 2017-01-20
    相关资源
    最近更新 更多