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

Typescript модульные системы на момент JJ ведут себя странно

Я пытаюсь использовать momentJs из typescript: в зависимости от того, какую модульную систему я использую для компиляции typescript, я нахожу другое поведение в отношении того, как я могу использовать momentJs. При компиляции typescript с commonJs все работает так, как ожидалось, и я могу просто следить за документацией timeJs:

import moment = require("moment");
moment(new Date()); //this works

Если я использую "систему" как модульную систему typescript, когда я импортирую "момент", я вынужден делать

import moment = require("moment");
moment.default(new Date()); //this works
moment(new Date()); //this doesn't work

Я нашел обходное решение, чтобы заставить их работать независимо от используемой системы typescript

import m = require("moment")
var moment : moment.MomentStatic;
moment = (m as any).default || m;

Мне это не нравится, и я хотел бы понять, почему он ведет себя так. Я делаю что-то неправильно? Может ли кто-нибудь объяснить мне, что происходит?

4b9b3361

Ответ 1

Это происходит потому, что SystemJS автоматически преобразует moment в модуль в стиле ES6, обернув его в объект модуля, а CommonJS - нет.

Когда CommonJS втягивается moment, мы получаем фактическую функцию moment. Это то, что мы делали в JavaScript на некоторое время, и должно выглядеть очень хорошо. Это как если бы вы написали:

var moment = function moment() {/*implementation*/}

Когда SystemJS тянет moment, он не дает вам моментальную функцию. Он создает объект с функцией момента, присвоенной свойству с именем default. Это как если бы вы написали:

var moment = {
    default: function moment() {/*implementation*/}
}

Почему это так? Поскольку модуль должен быть отображением одного или нескольких свойств, а не функции, согласно ES6/TS. В ES6 соглашение для массивных внешних библиотек, которые ранее экспортировались, состоит в том, чтобы экспортировать себя в свойстве default объекта модуля с помощью export default (подробнее здесь; в ES6/ TypeScript вы можете импортировать такие функции, как это, используя синтаксис compact import moment from "moment").

Вы ничего не делаете неправильно, вам просто нужно выбрать формат ваших импортированных модулей и придерживаться вашего выбора. Если вы хотите использовать как CommonJS, так и SystemJS, вы можете изучить их настройку, чтобы использовать тот же стиль импорта. Поиск 'systemjs default import' привел меня к этой дискуссии вашей проблемы, в которой они реализуют настройку --allowSyntheticDefaultImports.

Ответ 2

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

Я установил 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

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

Ответ 3

Момент был большой проблемой для проекта, над которым я работаю, но мы решили его решить, используя это:

import momentRef = require('moment');
var moment: moment.MomentStatic = momentRef;

Ответ 4

Вот как я это сделал с System.js и Typescript 1.7.5

import * as moment from "moment";
...
moment.utc(); // outputs 2015 (for now).

Но обратите внимание, что я использую метод utc(). Я не могу использовать moment(), потому что как mk. объяснил, что он преобразуется в moment.default() с помощью System.js. Причина Определенно типизированные типизации не содержат метода default, поэтому, чтобы избежать ошибки компиляции, нужно было бы использовать что-то вроде moment["default"]() (я знаю, уродливо).

Следующий шаг, мне нужно добавить в конфигурацию System.js следующее:

System.config({
  paths: {
    'moment': 'node_modules/moment/moment.js'
  }
});

После этого все работало как прелесть.

Ответ 5

Для моего system.config:

paths: {
    'moment': 'node_modules/moment/moment.js'
},
packages: {
    app: {
        format: 'register',
        defaultExtension: 'js'
    }
}

Импорт импульсов в моем компоненте Я удалил *, который, как я думаю, обрабатывает код в файле moment.js как несколько объектов.

Изменить:

import * as moment from 'moment';

в

import moment from 'moment';

Ответ 6

У меня был

import * as moment from 'moment';

и изменил все, что я думал, должно быть

var date: moment = moment();

к

var date: moment.Moment = moment();