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
?
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
?
@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.
moment.d.ts
em node_modules/@types/moment
/// <reference path="./node_modules/moment/moment.d.ts" />
em seu arquivo .ts
tsc --typeRoots node_modules test.ts
./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;
}
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:
// export = moment
no arquivo moment.d.ts oficialnode_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:
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.
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.
Comentários muito úteis
+1 por favor conserte isso