สามารถนำเข้า 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'));
});

เมื่อฉันเรียกใช้โครงสร้างอึกฉันได้รับข้อความ: "../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; }

ฉันสามารถรับข้อผิดพลาดที่สองหายไปได้ แต่ฉันยังต้องการคำสั่งที่ต้องการเพื่อให้ได้เวลาทำงานใน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

อัปเดต

เห็นได้ชัดว่าขณะนี้ให้คำจำกัดความประเภทของตัวเอง (ตามsivabudhอย่างน้อยตั้งแต่ 2.14.1 ขึ้นไป) ดังนั้นคุณไม่จำเป็นต้องมีtypingsหรือ@typesเลย

import * as moment from 'moment' ควรโหลดคำจำกัดความประเภทที่มาพร้อมกับแพ็คเกจ npm

ที่กล่าวว่าอย่างไรก็ตามในขณะที่กล่าวในช่วงเวลา / ดึง / 3319 # issuecomment-263752265 (คนที่พวกเขายังคงค้นหาที่ดูแลพวกเขา) ทีมขณะที่ดูเหมือนว่าจะมีปัญหาบางอย่างในการรักษาคำนิยามเหล่านั้น


คุณต้องติดตั้งการmomentพิมพ์โดยไม่มี--ambientธง

จากนั้นรวมโดยใช้ import * as moment from 'moment'


ที่ได้ผล คุณสามารถอธิบายความแตกต่างระหว่างการใช้--ambientธงกับไม่ได้หรือไม่? ฉันได้รับตัวเลขในการทำงานโดยใช้แฟล็กแวดล้อม นอกจากนี้หน้าหลักnpmjs.com/package/typings ยังให้ตัวอย่างโดยใช้ค่าสถานะแวดล้อม ฉันไม่รู้ว่าเมื่อไหร่ที่ฉันต้องการ / จำเป็นต้องใช้อีกอันหนึ่ง ขอบคุณ!
peinearydevelopment

1
บอกตามตรงว่าทำไม่ได้ โดยปกติคุณใช้--ambientแฟล็กสำหรับนิยาม typescript ทั้งหมดจากtypings/ DefinitelyTypedแต่momentนิยามมีโครงสร้างแปลก ๆ และไฟล์ไม่ได้รับการดาวน์โหลดอย่างถูกต้อง หากคุณดูไฟล์นิยามmoment.d.tsมันมีเพียงการอ้างอิงถึงเวอร์ชันโหนดซึ่งไม่ได้รับการแก้ไขเมื่อดาวน์โหลด (อาจคุ้มค่าที่จะเปิดปัญหา)
ช่วย

เห็นได้ชัดว่ามีประเด็นที่เกี่ยวข้องกับปัญหานี้อยู่แล้ว: github.com/DefininiteTyped/DefininiteTyped/issues/8388
peinearydevelopment

1
ฉันทำให้มันใช้งานได้โดยใช้ import * as moment จาก 'moment / moment' b / c มันถูกติดตั้งเป็นโฟลเดอร์ย่อยในโฟลเดอร์ node-modules
user441058

1
ฉันใช้ webpack และขณะนี้เวอร์ชัน 2.17.1 แต่ยังไม่สามารถใช้งานได้ ฉันพยายาม: นำเข้า * เป็นช่วงเวลาจาก 'ช่วงเวลา'; และนำเข้า * เป็นช่วงเวลาจาก 'ช่วงเวลา / ช่วงเวลา'; และไม่ทำงาน!
Mohy Eldeen

59

คุณต้องนำเข้าmoment ()ฟังก์ชันและช่วงเวลา the class แยกกันใน TS

ผมพบว่าบันทึกในเอกสาร typescript ที่นี่

/ * ~ โปรดทราบว่าโมดูล ES6 ไม่สามารถส่งออกฟังก์ชันที่เรียกได้โดยตรง
* ~ ไฟล์นี้ควรนำเข้าโดยใช้ CommonJS-style:
* ~ import x = require ('someLibrary');

ดังนั้นโค้ดที่จะนำเข้าช่วงเวลา js ไปยัง typescript จะมีลักษณะดังนี้:

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 = ต้องใช้ ('moment');
Telmo Pimentel Mota

จริงๆแล้วคุณยังสามารถใช้moment.Momentอินเทอร์เฟซได้โดยตรงจากเนมสเปซmoment
HalfWebDev

20

ไม่แน่ใจว่าสิ่งนี้เปลี่ยนแปลงไปเมื่อใด แต่ด้วย typescript เวอร์ชันล่าสุดคุณก็ต้องใช้ import moment from 'moment';และทุกอย่างอื่นควรทำงานได้ตามปกติ

อัพเดท:

ดูเหมือนว่าช่วงเวลาล่าสุดจะแก้ไขการนำเข้าของพวกเขา อย่างน้อยที่สุด2.24.0คุณจะต้องใช้import * as moment from 'moment';


5
import * as moment from 'moment'จะไม่ทำงานกับ typescript แต่import moment from 'moment'ทำ
Stuart McIntyre

มันใช้งานได้ แต่ฉันได้รับเวลา GMT 0 แต่ฉันต้องการเวลาท้องถิ่นซึ่งใช้งานไม่ได้ฉันก็ลองใช้ moment (). utc (). format () แต่มันกำลังรักษาผลลัพธ์เดียวกัน
kbhaskar

@kbhaskar เป็นเวอร์ชันล่าสุดที่พวกเขาแก้ไขการนำเข้า ดูคำตอบที่อัปเดต
NSjonas

1
ฉันคิดว่ามันน่ารักมากทีเดียว ขั้นตอนเพิ่มเติมเพียงอย่างเดียวที่ฉันต้องทำคือเพิ่มesModuleInteropset trueใน config ของฉันซึ่งฉันได้รับจากคำตอบนี้ ขอบคุณ.
Mark Birbeck

14

ผ่านการพิมพ์

Moment.js รองรับ TypeScript ใน v2.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.

ใช่ฉันยืนยันว่านี่คือคำตอบที่แท้จริง ทำงานอย่างมีเสน่ห์
Capy

เมื่อฉันพยายามทำสิ่งนี้โดยใช้ npm i @ types / moment ฉันได้รับข้อผิดพลาด: TypeScript error: src \ app.ts (1,1): error TS7038: ไม่สามารถเรียกหรือสร้างการนำเข้าสไตล์เนมสเปซได้และจะทำให้ ความล้มเหลวที่รันไทม์ บน tsc -v 2.7.2
GONeale

2

ฉันเพิ่งสังเกตว่าคำตอบที่เพิ่มคะแนนและแสดงความคิดเห็นนั้นคลุมเครือ ดังนั้นสิ่งต่อไปนี้คือสิ่งที่เหมาะกับฉัน ฉันกำลังใช้ Moment 2.26.0และ TS3.8.3 :

ในรหัส:

import moment from 'moment';

ใน TS config:

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

ฉันกำลังสร้างทั้งสองอย่าง CommonJS และ EMS ดังนั้นการกำหนดค่านี้จึงถูกนำเข้าสู่ไฟล์กำหนดค่าอื่น ๆ

ข้อมูลเชิงลึกมาจากคำตอบนี้ซึ่งเกี่ยวข้องกับการใช้ Express ฉันคิดว่ามันคุ้มค่าที่จะเพิ่มที่นี่เพื่อช่วยทุกคนที่ค้นหาเกี่ยวกับ Moment.js แทนที่จะเป็นสิ่งที่กว้างกว่า


จากนั้นคุณสามารถใช้moment()แบบปกติแทนmoment.default()
xinthose

0

1. ติดตั้งช่วงเวลา

npm install moment --save

2. ทดสอบรหัสนี้ในไฟล์ typescript ของคุณ

import moment = require('moment');

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

1
นี่ไม่ใช่วิธีที่เหมาะสมในการนำเข้าโมดูลใน typescript โปรดพิจารณาอัปเดตคำตอบของคุณ อ้างถึงสิ่งนี้เพื่อยืนยัน: 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แพ็กเกจเนื่องจากรวมประเภทไว้แล้ว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.