Moment: [TypeScript] "erro TS2304: Não é possível encontrar o nome 'momento'" quando usado com "módulo": "nenhum"

Criado em 14 fev. 2017  ·  51Comentários  ·  Fonte: moment/moment

O typescript parece não ser capaz de resolver a função global moment() quando usada em um contexto não-módulo.

versão tsc: 2.1.6
versão do momento: 2.17.1

Repro (assumindo que tsc esteja em seu $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'.

No entanto, usar um tipo de módulo funciona conforme o esperado:

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

Infelizmente, meu projeto não usa um bundler ou sistema de módulo, então estou preso com "module": "none" por enquanto.

Minha única alternativa é usar algo como typings install --save --global dt~moment ?

TypeScript Up-For-Grabs

Comentários muito úteis

+1 por favor conserte isso

Todos 51 comentários

Estou enfrentando o mesmo problema. Não importa o tipo de módulo que você especifica em tsconfig.json. Recebo o mesmo erro que @rossipedia

Eu relatei o mesmo problema (https://github.com/moment/moment/issues/3663), mas infelizmente foi fechado sem qualquer reação.

Acabei copiando moment.d.ts em meu diretório /scripts/app e implementei a correção especificada em https://github.com/moment/moment/issues/3663#issuecomment -273199291

Esperançosamente, uma correção mais permanente chegará a moment.d.ts eventualmente.

Resolvi isso especificando "moduleResolution": "node" em meu tsconfig. Não tenho certeza se essa é uma opção para vocês, mas parece funcionar.

"moduleResolution": "node" não corrigiu para mim, infelizmente

@rossipedia Me também.

Não ajudaria a adicionar export as namespace moment; no arquivo moment.d.ts ?

Veja: https://github.com/moment/moment/issues/3808

@czb que também não corrigiu o problema para mim, infelizmente :(

Resolvi isso usando alguns hacks que outros mencionaram em torno de uma tonelada de problemas em muitos projetos que estão tendo esse problema. Basta envolvê-lo em um arquivo de definição personalizado de sua preferência. Isso está usando o Typescript 2.2. Dessa forma, não estou mexendo com a dependência que vem do npmjs.org e não tenho que verificar tudo no controle de origem.

tsconfig.json

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

moment.custom.d.ts

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

Estou curioso para saber por que isso não funciona quando esse código é adicionado diretamente a moment.d.ts ? Não posso deixar de pensar que estamos nos intrometendo em algum bug obscuro de resolução do TypeScript e, infelizmente, tsc não tem um modo verboso (que eu saiba) que ajudaria a identificar onde as coisas estão dando errado.

Eu acho que se você definir "module": "none" typescript não procurará d.ts arquivos na pasta node_modules/moment . Minha experiência é que ele está apenas procurando na pasta node_modules/@types . Portanto, existem basicamente essas opções.

  1. Copie moment.d.ts em node_modules/@types/moment
  2. Inclua /// <reference path="./node_modules/moment/moment.d.ts" /> em seu arquivo .ts
  3. Ligue para tsc --typeRoots node_modules test.ts
  4. Coloque ./node_modules/moment/moment.d.ts em files seção de tsconfig.json

Você também precisa adicionar export as namespace moment; no arquivo moment.d.ts .

a equipe do Moment adoraria qualquer PRs que consertasse isso, mas continuasse compatível com o TS 1.x.

Ainda não encontrei uma solução que funcione, mas quando o fizer, com certeza adicionarei um PR

De acordo com o # 3663, a correção temporária para fazê-lo funcionar sem qualquer empacotador ...

  • Copie moment.d.ts de node_modules/moment/ para node_modules/@types/moment

  • Altere export = moment; em moment.d.ts para

declare module "moment" {
    export = moment;
}
  • Renomear moment.d.ts para index.d.ts

Use o momento e seu editor (no meu caso vscode) e tsc não devem reclamar

+1 por favor conserte isso

@mtgibbs Onde você está colocando o arquivo moment.custom.d.ts? Existe alguma outra configuração que precisa acontecer para que seu aplicativo encontre este arquivo custom.d.ts?

@elSteeze

Sim, estou adicionando-os ao meu tsconfig.json . Aqui está um exemplo simples:

{
  "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 Ei, obrigado cara! Agradeço a resposta rápida. Vou tentar.

@mtgibbs Desculpe por outra pergunta do tipo noob, depois de implementar sua solução comecei a receber erros do editor na palavra-chave moment em meu código ts ...

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

Fiz algumas pesquisas pessoais e tentei implementar uma solução reescrevendo moment.custom.d.ts, mas, infelizmente, isso não corrigiu meu problema.

Desculpe, não estou tentando ser um daqueles devs irritantes que fazem todo mundo depurar seu código, sou recém-formado e iniciante no trabalho com bibliotecas de terceiros em um ambiente Angular 2

Aqui está meu module.custom.d.ts atualizado

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

Sem problemas. Se estiver usando Angular 2, você deve usar 2.0+ TS. Eu não trabalho no Angular, então não tenho certeza. Lembre-se de colar o que puder do seu tsconfig.json e eu darei uma olhada depois de voltar para um computador real.

Certo!

Este é todo o meu arquivo tsconfig.es5.json dentro do diretório src do meu módulo angular 2 que estou construindo.
Agradeço a ajuda aliás

{
  "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"
  ]
}

Em qual versão do TS você está compilando? Você deve apenas ser capaz de importar o momento no topo sem meu hack.

@mtgibbs Estou usando a v2.2 e foi o que pensei. Infelizmente, não está funcionando. Estou quase no ponto em que escrevo minha própria versão da funcionalidade que estamos tirando de momentjs, porque não consigo fazer isso funcionar.

@elSteeze

Ok, voltando aqui. Percebi que você disse que fez um module.custom.d.ts , mas então se refere ao meu moment.custom.d.ts no seu tsconfig.json . Certifique-se de ter feito moment.custom.d.ts e adicionado ao seu compilador, nada daquelas coisas extras que você tinha ao declarar coisas. Em seguida, certifique-se de que está fazendo referência a ele na parte superior do arquivo no qual deseja usá-lo.

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

Isso deve permitir que você faça referência a ele como uma variável global, como na minha solução alternativa original.

Ótimo, obrigado @mtgibbs ! Eu realmente agradeço a ajuda.
Eu alterei minha estrutura de arquivo para suportar seus caminhos. Portanto, esses são caminhos corretos.
Saúde, companheiro!

Isso funciona para mim:

  • comente // export = moment no arquivo moment.d.ts oficial
  • adicione node_modules/moment/moment.d.ts a tsconfig.json

Como alternativa, copie o moment.d.ts modificado para um local de sua escolha e adicione o caminho para ele no seu tsconfig.json

Acho que o principal problema é que, ao usar explicitamente "module":"none" em tsconfig.json, você não pode ter nenhuma importação ou exportação de nível superior em nenhuma biblioteca (porque você está usando módulos).

você tem que primeiro importar no componente como
importar * como momento de "momento";

Isso funcionou bem para mim

você tem que primeiro importar no componente como
importar * como momento de "momento";
Isso funcionou bem para mim

Se você fizer isso em um arquivo, a resolução do namespace será desabilitada para esses arquivos.

Por favor, pessoal, +1 para consertar isso

Por que você não corrige esse problema? É muito importante.

Adicionar "module": "commonjs" a tsconfig.json corrigiu para mim

Mas eu tenho que usar "module": "none" . Commonjs não é uma solução.

Se estou entendendo corretamente, isso será resolvido com o recurso de import ing definições de tipo sem afetar o contexto do módulo / ambiente.

Estou usando o TS 3.0.1. Isso já está resolvido? Não funciona fora da caixa, pelo menos.

EDIT , com TS 3.0.1 eu poderia fazer apenas isso:

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

Viva!

Com tsconfig

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

O TS 3.0.1 parece resolver esse problema (e está aberto há mais de um ano e meio sem tração)

Olá rossipedia,
Estou enfrentando o mesmo problema no projeto angular-6. De acordo com seus comentários, está resolvido no TS 3.0.1, mas o angular6 CLI não oferece suporte ao TypeScript versão 3.0.1.

Você pode ajudar a resolver este problema?

Alguém mais encontrou o pacote @types/moment npm, que é apenas um esboço e diz para você usar o arquivo fornecido pelo pacote moment normal?

... Por que o Momento tem que fazer isso de forma diferente em comparação com qualquer outro pacote? Esta é a razão pela qual esse problema existe, e milhares de horas foram gastas pelos desenvolvedores lutando contra isso.

Claro, a solução da @Ciantic funciona no TS 3.0.1, mas não preciso usar algo como declare var moment: typeof import("moment"); para nenhum dos outros pacotes que estou usando.

Não parece que o Typescript 3.0.1 corrigiu esse problema, parece que apenas nos dá uma solução alternativa.

parece que apenas nos dá uma solução alternativa.

Sim, é exatamente isso. Esta não é uma "correção" aceitável.

Faz apenas um dia e eu percebi que a solução alternativa do TS 3.0.1 importa apenas a função moment , não o namespace / tipos. Então, se você quiser passar um objeto de momento para uma função, isso acontece:

image

Reabra este problema, ou melhor: corrija o arquivo .dts.

Não é uma solução para o problema original, mas para as pessoas que pesquisam isso mais tarde: a especificação do seguinte em tsconfig.json corrigiu o problema (texto datilografado 3.3.3 e momento 2.24.0)

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

Não estou usando muito o momento atualmente, mas estou feliz em reabrir o problema se ele ainda for válido.

ERRO em src / app / services / get-list.service.ts (22,54): erro TS2304: Não é possível localizar o nome '_'.

Qual é a solução para isso??

@nagipogu Nenhuma solução para isso, este problema é para moment.js , por favor, abra seu problema no repositório Github do underscore.js .

Estou tendo esse problema com a versão mais recente do momento com a versão mais recente do TS. Alguém tem alguma solução alternativa bem-sucedida?

Ainda não funcionando, a solução para mim foi yarn add -W [email protected] .

Quando instalei a última versão do Momento e olhei para node_modules / moment / package.json, vi o seguinte: https://github.com/moment/moment/blob/develop/package.json#L29 - mas não havia diretório existente node_modules/moment/ts3.1-typings , então não é surpresa que TS não conseguisse encontrá-lo. Acho que pode haver algum bug com um script de instalação (ou um pacote) ou assim. Sim, temos "module": "esnext" em tsconfig.json.

Para mim, quebrou com 2.25.0:

Usei pnpm add [email protected] como uma solução temporária.

Para mim, quebrou com 2.25.0:

Usei pnpm add [email protected] como uma solução temporária.

funciona bem obrigado

Para mim, quebrou com 2.25.0:

Usei pnpm add [email protected] como uma solução temporária.

Mesmo aqui adicionado a: "dependencies" {"moment": "^ 2.24.0",
} ... parece funcionar, obrigado.

O downgrade para 2.24.0 também funcionou para mim. Parece uma regressão em 2.25.0.

2.25.3 corrige seus problemas?

Existem tantos tipos diferentes de situações em que Moment.js é usado, muito menos TS 1.x, TS 2.x, TS 3.x ...
Hesito em fazer mudanças que quebrem qualquer grupo desses usuários.

Se você acha que a documentação pode ser melhorada, poste em https://github.com/moment/momentjs.com/

2.25.3 corrige seus problemas?

sim.

Revertido para 2.24.0 quando 2.25.1 falhou para mim no Angular 9. Com 2.25.3 está de volta aos trilhos.

OK ótimo. Vou fechar por agora.

Por favor, reabra (ou abra um novo problema) se você ainda tiver dúvidas.

Esta página foi útil?
0 / 5 - 0 avaliações