Como o moment.js pode ser importado com o typescript?

93

Estou tentando aprender o texto datilografado. Embora eu não ache que seja relevante, estou usando o VSCode para esta demonstração.

Eu tenho um package.jsonque contém estas peças:

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

Então eu tenho uma classe Typescript main.jscomo esta:

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

Minha gulpfile.jsaparência é esta:

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'));
});

Quando executo o gulp build, recebo a mensagem: "../main.ts(1,25): Cannot file module 'moment'."

Se eu usar import moment = require('moment');, o jspm funcionará e trará o módulo quando executar o aplicativo, mas continuo recebendo o erro de compilação. Eu também tentei:

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

Em vez de melhorar o problema, ele piorou. Agora recebo o erro acima na compilação, bem como o seguinte:"../typings/browser/ambient/moment/index.d.ts(9,21): Cannot find namespace 'moment'."

Se eu for para o arquivo fornecido por digitação e adicionar no final do arquivo:

declare module "moment" { export = moment; }

Posso fazer com que o segundo erro desapareça, mas ainda preciso da instrução require para conseguir o momento de trabalhar em meu main.tsarquivo e ainda estou recebendo o primeiro erro de compilação.

Preciso criar meu próprio .d.tsarquivo por enquanto ou falta apenas alguma configuração?

peinearydevelopment
fonte
Adicionando esta atualização para qualquer um que se depara com isso agora: import moment, { Moment } from 'moment';permite que você faça const x = moment();econst x: Moment = moment();
ryuu9187
Nenhuma dessas soluções funcionou, mudei para cá - github.com/date-fns/date-fns
chrismarx

Respostas:

119

Atualizar

Aparentemente, momento agora fornece suas próprias definições de tipo (de acordo com sivabudh pelo menos a partir 2.14.1 para cima), assim você não precisa typingsou @typesem tudo.

import * as moment from 'moment' deve carregar as definições de tipo fornecidas com o pacote npm.

Dito isso, no entanto, como dito em moment / pull / 3319 # issuecomment-263752265, a equipe do momento parece ter alguns problemas para manter essas definições (eles ainda estão procurando por alguém que as mantém) .


Você precisa instalar momenttipificações sem a --ambientbandeira.

Em seguida, inclua-o usando import * as moment from 'moment'

Assessores
fonte
Isso funcionou. Você pode explicar a diferença entre usar a --ambientbandeira e não usar ? Consegui que o numeraljs trabalhasse com a ambient flag. Além disso, sua página principal npmjs.com/package/typings dá o exemplo usando o sinalizador de ambiente. Não sei quando quero / preciso usar um em vez do outro. Obrigado!
peinearydevelopment
1
Para ser honesto, não posso. Normalmente você usa o --ambientsinalizador para todas as definições de Typescript de typings/, DefinitelyTypedmas a momentdefinição tem uma estrutura estranha e os arquivos não são baixados corretamente. Se você olhar o arquivo de definição moment.d.ts, ele contém apenas uma referência à versão do nó, que não é resolvida no download (pode valer a pena abrir um problema).
Assessores de
Aparentemente, já existe um relacionado a esse problema: github.com/DefinitelyTyped/DefinitelyTyped/issues/8388
peinearydevelopment
1
Comecei a trabalhar usando import * como momento de 'momento / momento' b / c foi instalado como uma subpasta na pasta de módulos de nó.
user441058
1
Estou em um webpack, e agora a versão 2.17.1, mas ainda não consigo fazê-lo funcionar. Eu tentei: import * as moment from 'moment'; e importar * como momento de 'momento / momento'; e não está funcionando!
Mohy Eldeen
58

Você precisa importar moment () a função e Moment a classe separadamente no TS.

Eu encontrei uma nota na documentação datilografada aqui .

/ * ~ Observe que os módulos ES6 não podem exportar funções chamáveis ​​diretamente
* ~ Este arquivo deve ser importado usando o estilo CommonJS:
* ~ import x = require ('someLibrary');

Portanto, o código para importar moment js para o texto digitado realmente se parece com este:

import { Moment } from 'moment'
....
let moment = require('moment');
...
interface SomeTime {
  aMoment: Moment,
}
...
fn() {
  ...
  someTime.aMoment = moment(...);
  ...
}
Koby
fonte
1
Boa resposta, pois mostra a diferença entre o tipo e a função. Obrigado!
Jelle
não consigo encontrar o nome 'require'
Container Codificado
4
Agora, isso pode ser usado como import * as moment from 'moment';e depois usado moment.Momentpara digitações.
meteoro
O que funcionou para mim foi: import moment = require ('moment');
Telmo Pimentel Mota
Na verdade, você também pode usar a moment.Momentinterface diretamente do namespacemoment
HalfWebDev 01 de
19

Não tenho certeza de quando isso mudou, mas com a última versão do typescript, você só precisa usar import moment from 'moment';e tudo o mais deve funcionar normalmente.

ATUALIZAR:

Parece que o momento recente corrigiu sua importação. Pelo menos 2.24.0você vai querer usarimport * as moment from 'moment';

NSjonas
fonte
5
import * as moment from 'moment'não funcionará com texto datilografado, mas import moment from 'moment'funciona.
Stuart McIntyre
Está funcionando, mas estou obtendo a hora GMT 0, mas preciso da hora local que não está funcionando. Também tento com moment (). Utc (). Format () mas está retornando o mesmo resultado.
kbhaskar de
@kbhaskar na última versão do momento em que corrigiu sua importação. Ver resposta atualizada
NSjonas
1
Acho que é basicamente isso. A única etapa adicional que tive de fazer foi adicionar esModuleInteropset to truena minha configuração, que obtive com esta resposta . Obrigado.
Mark Birbeck
14

via digitação

Moment.js agora oferece suporte a TypeScript na v2.14.1.

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


Diretamente

Pode não ser a melhor resposta, mas este é o caminho da força bruta e funciona para mim.

  1. Basta baixar o moment.jsarquivo real e incluí-lo em seu projeto.
  2. Por exemplo, meu projeto se parece com este:

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

  1. E aqui está um exemplo de código-fonte:

`` `

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. Use apenas nodepara correr main.js.
Sivabudh
fonte
Sim, eu confirmo que esta é a resposta correta. Funcionou como um encanto.
Capy de
Quando tento fazer isso usando npm i @ types / moment, recebo um erro: Erro de TypeScript: src \ app.ts (1,1): erro TS7038: Uma importação de estilo de namespace não pode ser chamada ou construída e causará uma falha no tempo de execução. em tsc -v 2.7.2
GONeale
1

Acabei de notar que a resposta que votei e comentei é ambígua. Portanto, o que se segue é exatamente o que funcionou para mim. Atualmente estou no Moment 2.26.0and TS 3.8.3:

Em código:

import moment from 'moment';

Na configuração do TS:

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

Estou construindo para tanto commonjs e EMS para que esta configuração é importado para outros arquivos de configuração.

O insight vem desta resposta que se refere ao uso do Express. Achei que valia a pena adicionar aqui, porém, para ajudar qualquer pessoa que pesquisa em relação ao Moment.js, ao invés de algo mais geral.

Mark Birbeck
fonte
então você pode usar moment()normalmente em vez demoment.default()
xinthose
0

1. momento de instalação

npm install moment --save

2. teste este código em seu arquivo typescript

import moment = require('moment');

console.log(moment().format('LLLL'));
lutula resistente
fonte
1
Esta não é a maneira adequada de importar um módulo no texto datilografado. Considere atualizar sua resposta. Consulte isto para confirmação: basarat.gitbook.io/typescript/project/modules/external-modules
Efe Ariaroo
0

Ainda quebrado? Tente desinstalar @types/moment.

Então, removi o @types/momentpacote do package.jsonarquivo e funcionou usando:

import * as moment from 'moment'

As versões mais recentes momentdo não requerem o @types/momentpacote porque os tipos já estão incluídos.

Ben Winding
fonte