Як можна імпортувати moment.js за допомогою TypeScript?


96

Я намагаюся вивчити 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'."

Якщо я перейду до файлу, наданого типізацією, і додаю внизу файлу:

declare module "moment" { export = moment; }

Я можу зникнути другу помилку, але мені все ще потрібен оператор require, щоб отримати момент для роботи у моєму main.tsфайлі, і я все ще отримую першу помилку збірки.

Чи потрібно мені створювати власний .d.tsфайл на певний момент, чи мені просто не вистачає якоїсь частини налаштування?


1
Додавання цього оновлення для тих, хто стикається з цим зараз: import moment, { Moment } from 'moment';дозволяє це зробити const x = moment();іconst x: Moment = moment();
ryuu9187

Жодне з цих рішень не спрацювало, я переїхав сюди - github.com/date-fns/date-fns
chrismarx

Відповіді:


124

Оновлення

Очевидно, зараз moment надає власні визначення типу (згідно з sivabudh принаймні з 2.14.1 вгору), отже, вам це не потрібно typingsабо @typesвзагалі.

import * as moment from 'moment' повинен завантажувати визначення типів, надані разом із пакетом npm.

Однак, як зазначено в moment / pull / 3319 # issuecomment-263752265, у команди на даний момент, мабуть, є деякі проблеми з підтримкою цих визначень (вони все ще шукають того, хто їх підтримує) .


Вам потрібно встановити momentтипізацію без --ambientпрапора.

Потім включіть його за допомогою import * as moment from 'moment'


Це спрацювало. Чи можете ви пояснити різницю між використанням --ambientпрапора та ні? Я отримав numeraljs для роботи, використовуючи навколишній прапор. Крім того, на їхній головній сторінці npmjs.com/package/typings подано приклад використання прапора навколишнього середовища. Я не знаю, коли б мені хотілося / потрібно було використовувати одне над іншим. Дякую!
peinearydevelopment

1
Чесно кажучи, не можу. Зазвичай ви використовуєте --ambientпрапор для всіх визначень Typescript з typings/, DefinitelyTypedале momentвизначення має дивну структуру, і файли завантажуються неправильно. Якщо ви подивитесь на файл визначення moment.d.ts, він містить лише посилання на версію вузла, яка не вирішується при завантаженні (можливо, варто відкрити проблему).
помічники

Очевидно, що вже є одне, що стосується цього питання: github.com/DefinitelyTyped/DefinitelyTyped/issues/8388
peinearydevelopment

1
Я змусив його працювати, використовуючи імпорт * як момент з моменту "момент / момент" b / c, він був встановлений як підпапка в папці node-modules.
user441058 04

1
Я перебуваю у веб-пакеті, і зараз версія 2.17.1, але все ще не можу змусити його працювати. Я спробував: імпортувати * як момент від 'моменту'; та імпортувати * як момент від 'момент / момент'; і не працює!
Мохі Елдін,

59

Вам потрібно імпортувати функцію moment () функції та Moment класу окремо в TS.

Я знайшов примітку в документах машинопису тут .

/ * ~ Зверніть увагу, що модулі ES6 не можуть безпосередньо експортувати функції, що викликаються
* ~ Цей файл слід імпортувати, використовуючи стиль CommonJS:
* ~ import x = require ('someLibrary');

Отже, код для імпорту моменту js у typecript насправді виглядає так:

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

1
Хороша відповідь, оскільки вона показує різницю між типом і функцією. Дякую!
Jelle den Burger

не можу знайти ім'я "вимагати"
кодований контейнер

4
Тепер це можна використовувати як, import * as moment from 'moment';а потім використовувати moment.Momentдля набору тексту.
метеор

У мене спрацювало: import moment = require ('moment');
Тельмо Піментел Мота

Насправді ви також можете використовувати moment.Momentінтерфейс безпосередньо з простору іменmoment
HalfWebDev

20

Не впевнений, коли це змінилося, але з останньою версією машинопису вам просто потрібно використовувати, import moment from 'moment';а все інше має працювати як зазвичай.

ОНОВЛЕННЯ:

Схоже, що нещодавно виправлено імпорт. Принаймні 2.24.0ви хочете використовуватиimport * as moment from 'moment';


5
import * as moment from 'moment'не буде працювати з машинописом, але import moment from 'moment'працює.
Стюарт Макінтейр

Він працює, але я отримую час GMT 0, але мені потрібен місцевий час, який не працює, я також намагаюся з моментом (). Utc (). Format (), але він повертає той самий результат.
kbhaskar,

@kbhaskar станом на останню версію моменту, коли вони виправили імпорт. Дивіться оновлену відповідь
NSjonas

1
Я думаю, що це майже все. Єдиним додатковим кроком, який мені довелося зробити, було додати esModuleInteropset до trueмого конфігура, який я отримав із цієї відповіді . Дякую.
Марк Бірбек,

14

за допомогою набору тексту

Moment.js тепер підтримує TypeScript у версії 2.14.1.

Див .: 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: src \ app.ts (1,1): помилка TS7038: Імпорт у стилі простору імен не може бути викликаний або побудований, і це спричинить збій під час виконання. на tsc -v 2.7.2
GONeale

2

Я щойно помітив, що відповідь, яку я підтримав і прокоментував, є неоднозначною. Отже, саме те, що мені вдалося. Зараз я працюю на моменті 2.26.0та TS 3.8.3:

У коді:

import moment from 'moment';

У конфігурації TS:

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

Я будую як для CommonJS, так і для EMS, тому ця конфігурація імпортується в інші конфігураційні файли.

Розуміння випливає з цієї відповіді, яка стосується використання Express. Я зрозумів, що варто додати сюди, щоб допомогти кожному, хто шукає за Moment.js, а не чимсь загальнішим.


тоді ви можете використовувати moment()як звичайний замістьmoment.default()
xinthose

0

1. встановити момент

npm install moment --save

2. протестуйте цей код у своєму файлі машинопису

import moment = require('moment');

console.log(moment().format('LLLL'));

1
Це не належний спосіб імпортувати модуль у машинопис. Будь ласка, оновіть свою відповідь. Зверніться до цього для підтвердження: basarat.gitbook.io/typescript/project/modules/external-modules
Efe Ariaroo

0

Все ще зламаний? Спробуйте видалити @types/moment.

Отже, я видалив @types/momentпакет з package.jsonфайлу, і він працював за допомогою:

import * as moment from 'moment'

Новіші версії пакета momentне вимагають @types/momentпакета, оскільки типи вже включені.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.