Подтвердить что ты не робот

Как использовать momentjs в TypeScript с SystemJS?

Моя настройка проекта включает инструмент "jspm" для библиотек и инструмент "tsd" для типирования.

После установки момента TypeScript файла d.ts(этих) я не могу найти способ загрузки и фактического использования экземпляра момента.

В моем файле (с загрузкой модуля SystemJS)

/// <reference path="../../../typings/tsd.d.ts" />
import * as moment from "moment";
import * as _ from "lodash";
...
...
const now = (this.timestamp === 0) ? moment() : moment(this.timestamp);

Я получаю "TypeError: момент не является функцией"

Определения структурированы так же, как lodash, который отлично работает, поэтому я не знаю, что может быть причиной.

Может ли кто-нибудь помочь?

4b9b3361

Ответ 1

Я сделал следующее:

Я установил moment файл определения следующим образом:

tsd install moment --save

Затем я создал main.ts:

///<reference path="typings/moment/moment.d.ts" />

import moment = require("moment");
moment(new Date());

И я побежал:

$ tsc --module system --target es5 main.ts # no error 
$ tsc --module commonjs --target es5 main.ts # no error 

main.js выглядит следующим образом:

// https://github.com/ModuleLoader/es6-module-loader/blob/v0.17.0/docs/system-register.md - this is the corresponding doc
///<reference path="typings/moment/moment.d.ts" />
System.register(["moment"], function(exports_1) {
    var moment;
    return {
        setters:[
            function (moment_1) {
                // You can place `debugger;` command to debug the issue
                // "PLACE XY"
                moment = moment_1;
            }],
        execute: function() {
            moment(new Date());
        }
    }
});

Моя версия TypeScript - 1.6.2.

Вот что я узнал:

Momentjs экспортирует функцию (т.е. _moment = utils_hooks__hooks и utils_hooks__hooks - это функция, которая достаточно понятна.

Если вы разместите точку останова в месте, обозначенном мной как PLACE XY выше, вы увидите, что moment_1 является объектом (!), а не функцией. Соответствующие строки: 1, 2

В заключение этого проблема не имеет ничего общего с TypeScript. Проблема в том, что systemjs не сохраняет информацию о том, что momentjs экспортирует функцию. Systemjs просто копирует свойства экспортируемого объекта из модуля (функция также является объектом в JavaScript). Я думаю, вы должны указать проблему в репозитории systemjs, чтобы узнать, считают ли они, что это ошибка (или функция:)).

Ответ 2

Начиная с версии 2.13, момент включает в себя Typescript типизацию. Нет необходимости использовать tsd (или typings) больше.

В файле systemjs.config.js просто добавьте следующее:

  var map = {
    // (...)
    moment: 'node_modules/moment',      
  };

  var packages = {
    // (...)
    moment: { main: 'moment.js', defaultExtension: 'js' },
  };

И в модуле:

import moment = require('moment')

Ответ 3

У меня были огромные проблемы с тем, чтобы это работало, поскольку я не мог использовать npm из-за ограничений прокси (поэтому им пришлось вручную устанавливать библиотеки). Если версии моментов и определенные файлы установлены в соответствующих местах вашего проекта, вы можете заставить это работать с немного возиться.

Здесь полезно отметить на сайте moment.js по настройке typescript с моментом. Ключевым аспектом, который помог в моем случае, было добавить следующее в разделе compilerOptions моего файла tsconfig.json:

"allowSyntheticDefaultImports": true

Ответ 4

Это работает с Angular 2, но не должно быть специфичным для него. В основном вы говорите загрузчику System, где можно найти moment.min.js.

В system.config.js:

// map tells the System loader where to look for things
var map = {
  'app':                        'app', // 'dist',

  '@angular':                   'node_modules/@angular',
  'rxjs':                       'node_modules/rxjs',

  // tell system where to look for moment
  'moment':                     'node_modules/moment/min'
};

// packages tells the System loader how to load when no filename and/or no extension
var packages = {
  'app':                        { main: 'main.js',  defaultExtension: 'js' },
  'rxjs':                       { defaultExtension: 'js' },

  // tell system which file represents the script when you import
  'moment':                     { main: 'moment.min.js', defaultExtension: 'js'}
};

В вашем модуле:

import moment from 'moment';

ИЛИ (Редактировать 10/13/2016):

import * as moment from 'moment';

Некоторые комментаторы опубликовали синтаксис import * выше, и мне пришлось переключиться на это, а также после некоторых обновлений (не знаю, почему).

Ответ 5

В моем typescript файле, когда я использую

import moment from 'moment';

он говорит, что не может найти модуль "момент". Я установил момент как пакет npm, и он ссылается правильно, но по этой причине этот момент .d.ts экспортирует момент как пространство имен, а не модуль, как показано ниже, я не могу ссылаться на него.

export = moment; 

Итак, если я изменю его на

declare module 'moment' {
    export default moment;
}

импортирует работы отлично. Что я здесь делаю неправильно?

Ответ 6

Немного непонятно, пытаетесь ли вы использовать момент для разработки на стороне клиента или для серверной части (например, node.js). Но, если ваш случай является интерфейсом, то я смог использовать момент довольно легко:

1) Я просто добавил файлы в свой проект:

введите описание изображения здесь

2) Написал простой тестовый код:

window.onload = () =>
{
    var timestamp: number = 111111111111111;
    var momentResult: moment.Moment = moment(timestamp);
    alert(momentResult.toISOString());
};

И мой проект был построен нормально, и я видел тестовое предупреждение в браузере.

Ответ 7

Просто сделал это в моем проекте. Это angular, но я не думаю, что это имеет значение и может поставить вас на правильный путь. Это легко:

import MomentStatic = moment.MomentStatic;

class HelpdeskTicketController {
  constructor(private moment: MomentStatic) { // angulars dependency injection, you will have some global probably
    let d = this.moment(new Date()); // works
    console.log(d.add(2, 'hours').format()); // works
  }

  ...

Ответ 8

Я предполагаю, что момент был установлен с помощью

jspm install moment

Это должно добавить запись в раздел карты вашего config.js.

...
"moment": "npm:[email protected]",
...

Таким образом, вы можете получить доступ к моменту в файлах js через

import moment from 'moment';

console.log(moment().format('dddd, MMMM Do YYYY, h:mm:ss a'));

При импорте * as moment вы импортируете пространство имен модулей. Таким образом, момент будет объектом, свойства которого представляют собой экспорт модулей. Таким образом, экспорт по умолчанию не импортируется как момент, а как moment.default. Так что что-то вроде

moment.default().format('dddd, MMMM Do YYYY, h:mm:ss a')

может действительно работать в вашем коде, но не тот способ, которым он предназначен для использования.

Ответ 9

Для моих продуктов я использую Webpack с VS 2015 (обновление 3). Поэтому после добавления кодов для файлов package.json и webpack.config.vendor.js мне просто нужно вызвать import moment = require ('moment') на самом верху моего компонента (TypeScript, Angular 2).