Moment: [TypeScript] 与“模块”一起使用时出现“错误 TS2304:找不到名称‘时刻’”:“无”

创建于 2017-02-14  ·  51评论  ·  资料来源: moment/moment

在非模块上下文中使用时,Typescript 似乎无法解析全局moment()函数。

tsc 版本:2.1.6
时刻版本:2.17.1

重现(假设tsc在你的$PATH ):

$ mkdir repro && cd repro
$ npm i moment
$ echo 'const now = moment();' > test.ts
$ tsc --module none test.ts
test.ts(1,13): error TS2304: Cannot find name 'moment'.

但是,使用模块类型按预期工作:

$ echo 'import * as moment from "moment"; const now = moment();' > test2.ts
$ tsc --module commonjs test2.js

不幸的是,我的项目不使用捆绑器或模块系统,所以我现在坚持使用"module": "none"

我唯一的选择是使用typings install --save --global dt~moment吗?

TypeScript Up-For-Grabs

最有用的评论

+1 请解决这个问题

所有51条评论

我面临同样的问题。 您在 tsconfig.json 中指定的模块类型无关紧要。 我收到与@rossipedia相同的错误

我报告了同样的问题(https://github.com/moment/moment/issues/3663),但不幸的是它刚刚关闭而没有任何反应。

我最终将moment.d.ts复制到我的/scripts/app目录中并实施了https://github.com/moment/moment/issues/3663#issuecomment -273199291 中指定的修复

希望更永久的修复最终会进入moment.d.ts

我通过在 tsconfig 中指定"moduleResolution": "node"解决了这个问题。 不确定这是否适合你们,但它似乎可以解决问题。

不幸的是, "moduleResolution": "node"没有为我修复它

@rossipedia我也是。

export as namespace moment;moment.d.ts文件中会不会有帮助?

参见: https :

不幸的是,

我已经使用其他人在许多有此问题的项目中提到的大量问题的一些技巧解决了这个问题。 只需将其包装在您自己的自定义定义文件中即可。 这是使用 Typescript 2.2。 通过这种方式,我不会对来自 npmjs.org 的依赖感到困惑,而且我不必将整个事情检查到源代码管理中。

配置文件

"compilerOptions": {
    "target": "ES5",
    "moduleResolution": "node",
    ...
}

moment.custom.d.ts

import * as _moment from 'moment';
export as namespace moment;
export = _moment;

我很好奇为什么当该代码直接添加到moment.d.ts时这不起作用? 我不禁想到我们遇到了一些晦涩的 TypeScript 解析错误,不幸的是tsc没有详细模式(我知道)可以帮助查明问题出在哪里。

我认为,如果您定义"module": "none"打字稿不会在node_modules/moment文件夹下查找d.ts文件。 我的经验是它只在node_modules/@types文件夹下查看。 所以基本上有这些选项。

  1. 复制moment.d.ts下的node_modules/@types/moment
  2. /// <reference path="./node_modules/moment/moment.d.ts" />到您的.ts文件中
  3. 致电tsc --typeRoots node_modules test.ts
  4. ./node_modules/moment/moment.d.tsfilestsconfig.json

您还需要将export as namespace moment;moment.d.ts文件中。

Moment 团队会喜欢任何可以解决此问题的 PR,但要保持 TS 1.x 兼容。

我还没有找到一个完全可行的解决方案,但是当我找到时,我一定会添加一个 PR

根据 #3663 的临时修复,使其在没有任何捆绑器的情况下工作......

  • moment.d.tsnode_modules/moment/复制到node_modules/@types/moment

  • export = moment;中的moment.d.ts改为

declare module "moment" {
    export = moment;
}
  • moment.d.ts重命名index.d.ts

只需使用 moment 和您的编辑器(在我的情况下为 vscode )和 tsc 不应该抱怨

+1 请解决这个问题

@mtgibbs你把 moment.custom.d.ts 文件放在哪里? 您的应用程序是否需要进行任何其他配置才能找到此 custom.d.ts 文件?

@elSteeze

是的,我将它们添加到我的tsconfig.json 。 这是一个擦洗的示例:

{
  "compilerOptions": {
    "target": "ES5",
    "moduleResolution": "node",
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules",
    "./path/to/typings/**/*.d.ts",
    "./typings"
  ],
  "include": [
    "./path/to/typings/moment.custom.d.ts",
    "./path/to/src/**/*.ts"
  ]
}

@mtgibbs嘿,谢谢伙计! 感谢您的快速回复。 我会试试的。

@mtgibbs抱歉,另一个

'moment' refers to a UMD global, but the current file is a module. Consider adding an import instead

我做了一些个人研究,并试图通过重写 moment.custom.d.ts 来实现一个解决方案,但不幸的是,这并没有解决我的问题。

抱歉,不想成为那些让其他人调试他们代码的讨厌的开发人员之一,我是应届毕业生,我是在 Angular 2 环境中使用 3rd 方库的新手

这是我更新的 module.custom.d.ts

declare var moment: any;
declare var module: NodeModule;
interface NodeModule {
    id: string;
}
import * as _moment from 'moment';
export as namespace moment;
export = _moment;

没问题。 如果您使用的是 Angular 2,那么您应该使用 2.0+ TS。 我不在 Angular 工作,所以我不确定。 介意粘贴你的 tsconfig.json ,我会在我回到一台真正的计算机后看看。

当然!

这是我正在构建的 angular 2 模块的 src 目录中的整个 tsconfig.es5.json 文件。
顺便感谢您的帮助

{
  "compilerOptions": {
    "declaration": true,
    "module": "es2015",
    "target": "es5",
    "baseUrl": ".",
    "stripInternal": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "outDir": "../build",
    "rootDir": ".",
    "lib": [
      "es2015",
      "dom"
    ],
    "skipLibCheck": true,
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules",
    "./typings/**/*.d.ts",
    "./typings"
  ],
  "include": [
    "./typings/moment.custom.d.ts",
    "./src/**/*.ts"
  ],
  "angularCompilerOptions": {
    "annotateForClosureCompiler": true,
    "strictMetadataEmit": true,
    "skipTemplateCodegen": true,
    "flatModuleOutFile": "new-version-library.js",
    "flatModuleId": "new-version-library"
  },
  "files": [
    "./index.ts"
  ]
}

你编译的是什么版本的TS? 你应该能够在没有我的黑客的情况下在顶部导入时刻。

@mtgibbs我正在使用 v2.2,这就是我的想法。 不幸的是,它不起作用。 我几乎要编写我自己的从 momentjs 中获取的功能版本,因为我似乎无法使其正常工作。

@elSteeze

好的,回到这里。 我注意到你说你做了一个自定义的module.custom.d.ts ,但是你在你的tsconfig.json引用了我的moment.custom.d.ts tsconfig.json 。 确保你已经创建了moment.custom.d.ts并将它添加到你的编译器中,没有你声明它的那些额外的东西。 然后确保在要在其中使用它的文件的顶部引用它。

/// <reference path="path/to/your/moment.custom.d.ts" />

这应该允许您将其作为全局变量引用,就像我原来的解决方法一样。

太棒了,谢谢
我改变了我的文件结构来支持你的路径。 所以这些都是正确的路径。
队友的欢呼声!

这对我有用:

  • 注释掉官方moment.d.ts文件中的// export = moment
  • node_modules/moment/moment.d.tstsconfig.json

或者,将修改后的moment.d.ts复制到您选择的位置,并将其路径添加到您的tsconfig.json

我认为主要问题是在 tsconfig.json 中显式使用"module":"none" ,您不能在任何库中进行任何顶级导入或导出(因为您当时正在使用模块)。

您必须首先导入组件作为
从“时刻”导入 * 作为时刻;

它对我很有效

您必须首先导入组件作为
从“时刻”导入 * 作为时刻;
它对我很有效

如果您在文件中执行此操作,则会禁用该文件的命名空间解析。

请伙计们+1来解决这个问题

你为什么不解决这个问题? 这是非常重要的。

"module": "commonjs"tsconfig.json为我修复了它

但我必须使用"module": "none" 。 Commonjs 不是解决方案。

如果我理解正确,这将通过TypeScript 2.9 的导入类型功能解决,这将允许import类型定义而不影响模块/环境上下文。

我正在使用 TS 3.0.1,现在解决了吗? 至少它不是开箱即用的。

编辑,使用 TS 3.0.1 我可以做到这一点:

declare var moment: typeof import("moment");

欢呼!

使用 tsconfig

{
    "compilerOptions": {
        "module": "none"
        "moduleResolution": "node", 
        // ...
    }
}

TS 3.0.1 似乎解决了这个问题(它已经开放了一年半没有牵引力)

嗨罗西百科,
我在 angular-6 项目中面临同样的问题。 根据您的评论,它已在 TS 3.0.1 中解决,但 angular6 CLI 不支持 TypeScript 3.0.1 版。

你能帮忙解决这个问题吗?

有没有其他人也遇到过@types/moment npm 包,它只是一个存根并告诉您使用普通 moment 包提供的文件?

... 为什么与其他任何软件包相比,moment 必须以不同的方式执行此操作? 这就是这个问题存在的原因,开发人员为此花费了数千小时。

当然, @Ciantic的解决方案适用于 TS 3.0.1,但我不必对我正在使用的任何其他软件包使用类似declare var moment: typeof import("moment");东西。

看起来 Typescript 3.0.1 没有解决这个问题,它看起来只是给了我们解决方法。

看起来它只是给了我们解决方法。

是的,正是这个。 这不是一个可接受的“修复”。

这只是一天,我才意识到 TS 3.0.1 解决方法只导入moment函数,而不是命名空间/类型。 所以如果你想将一个 moment 对象传递给一个函数,就会发生这种情况:

image

请重新打开此问题,或者更好:修复 .dts 文件。

不是原始问题的解决方案,但对于稍后使用谷歌搜索的人:在 tsconfig.json 中指定以下内容修复了它(打字稿 3.3.3 和时刻 2.24.0)

{
  "compilerOptions": {
    "module": "commonjs"
  }
}

这些天我不再使用 moment 了,但如果它仍然有效,我很高兴重新打开这个问题。

src/app/services/get-list.service.ts(22,54) 中的错误:错误 TS2304:找不到名称“_”。

这是什么解决方案?

@nagipogu没有解决方案,这个问题是针对moment.js 的,请在underscore.js 的 Github 存储库中打开您的问题。

我在使用最新版本的 TS 时遇到了这个问题。 有没有人有任何成功的解决方法?

仍然无法正常工作,我的解决方案是yarn add -W [email protected]

当我安装最新的 moment 版本并查看 node_modules/moment/package.json 时,我看到了: https : node_modules/moment/ts3.1-typings ,所以 TS 找不到它也就不足为奇了。 我认为安装脚本(或包)等可能存在一些错误。 是的,我们在 tsconfig.json 中有"module": "esnext"

对我来说,它打破了 2.25.0:

我使用pnpm add

对我来说,它打破了 2.25.0:

我使用pnpm add

工作很好,谢谢

对我来说,它打破了 2.25.0:

我使用pnpm add

同样在这里将它添加到:"dependencies" {"moment": "^2.24.0",
} ...似乎工作谢谢。

降级到 2.24.0 也对我有用。 看起来像是 2.25.0 中的回归。

2.25.3 能解决你的问题吗?

使用 Moment.js 的情况有很多种,更不用说 TS 1.x、TS 2.x、TS 3.x……
我不愿做出会破坏这些用户组的更改。

如果您认为文档可以改进,请在https://github.com/moment/momentjs.com/发帖

2.25.3 能解决你的问题吗?

是的。

当 2.25.1 在 Angular 9 中失败时回滚到 2.24.0。在 2.25.3 中,它又回到了正轨。

好的,不错。 我会暂时关闭。

如果您仍有疑虑,请重新打开(或打开一个新问题)。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

RobinvanderVliet picture RobinvanderVliet  ·  3评论

slavafomin picture slavafomin  ·  3评论

BCup picture BCup  ·  3评论

benhathaway picture benhathaway  ·  3评论

IbraheemAlSaady picture IbraheemAlSaady  ·  3评论