programing

순간 스크립트 모듈 시스템 입력이상하게 행동하는 JS

bestprogram 2023. 7. 6. 22:27

순간 스크립트 모듈 시스템 입력이상하게 행동하는 JS

저는 타입스크립트에서 모멘트Js를 사용하려고 합니다: 타입스크립트를 컴파일하기 위해 사용하는 모듈 시스템에 따라 모멘트Js를 사용하는 방법에 대해 다른 동작을 발견합니다.commonJs로 typescript를 컴파일할 때 모든 것이 예상대로 작동하며 momentJs 문서를 따를 수 있습니다.

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

"moment"를 가져올 때 "system"을 유형 스크립트 모듈 시스템으로 사용하면 강제로 해야 합니다.

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

사용되는 스크립트 모듈 시스템에 관계없이 둘 다 작동할 수 있는 해결 방법을 찾았습니다.

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

저는 이것이 마음에 들지 않고, 왜 이렇게 행동하는지 이해하고 싶습니다.내가 뭘 잘못하고 있나요?무슨 일이 일어나고 있는지 설명해 줄 사람?

교체하여 문제를 해결했습니다.

import moment from "moment";

가져오기 문 포함

import * as moment from "moment";

이것.

은 System의 때문에 일어나는 일입니다.는 자동으로 JS를 .moment모듈 개체로 래핑하여 ES6 스타일 모듈로 이동합니다(공통).JS는 아닙니다.

공통인 경우JS가 들어오다moment우리는 실제를 이해합니다.moment 우리가 친숙해 입니다.이것은 우리가 자바스크립트에서 한동안 해왔던 것이고, 매우 친숙해 보일 것입니다.마치 다음과 같이 썼습니다.

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

시스템의 경우JS가 들어오다moment그것은 당신에게 모멘트 기능을 제공하지 않습니다.가 이이지속성할당모에함라는 된 객체를 .default마치 다음과 같이 썼습니다.

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

왜그요? 가진 이어야 하기 입니다.ES6/TS에 따르면 모듈은 함수가 아닌 하나 이상의 속성을 가진 맵이어야 하기 때문입니다.가 ES6에서 자체적으로 내보내는 입니다.default 을 사용합니다.export default(여기에서 자세히 읽어보십시오. ES6/TypeScript에서는 압축을 사용하여 다음과 같은 기능을 가져올 수 있습니다.import moment from "moment"구문)을 선택합니다.

잘못된 것이 아니라 가져온 모듈의 형식을 선택하고 원하는 대로 선택하면 됩니다.CommonJS와 System을 모두 사용하려는 경우JS, 동일한 가져오기 스타일을 사용하도록 구성할 수 있습니다.'systemjs default import'를 검색하여 문제에 대한 이 토론을 시작했습니다. 이 토론에서 문제는 다음과 같습니다.--allowSyntheticDefaultImports설정

다음을 수행했습니다.

는 습했니다를 설치했습니다.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 저장소에 문제를 제기해야 할 것 같습니다.

System.js 및 Typescript 1.7.5를 사용한 방법은 다음과 같습니다.

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

하지만 제가 사용하는 것은utc()방법.사용할 수 없습니다.moment()왜냐하면 mk.설명했지만, 이것은 로 변환됩니다.moment.default()system.js에 의해.Of Cause 확실히 유형화된 유형은 다음을 하지 않습니다.default방법, 그래서 컴파일 오류를 피하기 위해 다음과 같은 것을 사용해야 합니다.moment["default"]()(알아요, 못생겼어요)

다음 단계에서는 System.js 구성에 다음을 추가해야 했습니다.

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

그 후, 모든 것이 매력적으로 작용했습니다.

제가 진행 중인 프로젝트에 참여하는 것은 힘든 일이었지만, 결국 다음과 같은 방법으로 해결했습니다.

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

내 system.config의 경우:

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

구성 요소에서 momentjs를 가져오면서 moment.js 파일의 코드를 여러 개체로 처리하는 *를 제거했습니다.

변경:

import * as moment from 'moment';

대상:

import moment from 'moment';

나는 가지고 있었습니다

import * as moment from 'moment';

그리고 내가 생각했던 모든 것을 바꿨습니다.

var date: moment = moment();

로.

var date: moment.Moment = moment();

유형 스크립트를 사용하는 경우 다음과 같은 기본 가져오기import moment from "moment"와 동일하게 행동함const moment = require("moment").defaulthttps://www.typescriptlang.org/tsconfig#esModuleInterop 을 참조하십시오.

TLDR; 추가esModuleInterop: truetsconfig.json에서

만약 당신이 TypeScript를 사용하고 있다면,import * as moment from 'moment작동 중이지만 InSonarQube 필요한 특정 멤버를 명시적으로 가져오기 때문에 중요한 오류입니다.

명확한 코드가 더 나은 코드라는 원칙에 따라 모듈에서 사용할 항목을 명시적으로 가져와야 합니다.가져오기 *를 사용하면 모듈의 모든 항목을 가져오므로 유지 관리자가 혼동할 위험이 있습니다.마찬가지로 "module"에서 *을(를) 내보내고 모듈의 모든 내용을 가져온 다음 다시 내보냅니다. 그러면 유지 관리자뿐만 아니라 모듈 사용자도 혼동할 위험이 있습니다.

언급URL : https://stackoverflow.com/questions/32987273/typescript-module-systems-on-momentjs-behaving-strangely