ส่งออก typescript เทียบกับการส่งออกเริ่มต้น


273

ความแตกต่างใน typescript ระหว่างexportและdefault exportคืออะไร ในแบบฝึกหัดทั้งหมดฉันเห็นผู้คนกำลังเข้าร่วมexportชั้นเรียนของพวกเขาและฉันไม่สามารถรวบรวมรหัสของฉันถ้าฉันไม่เพิ่มdefaultคำหลักก่อนที่จะส่งออก

นอกจากนี้ฉันไม่สามารถหาร่องรอยของคำหลักที่การส่งออกเริ่มต้นใด ๆ อย่างเป็นทางการในเอกสารที่พิมพ์ด้วยพิมพ์ดีด

export class MyClass {

  collection = [1,2,3];

}

ไม่ได้รวบรวม แต่:

export default class MyClass {

  collection = [1,2,3];

}

ทำ.

ข้อผิดพลาดคือ: error TS1192: Module '"src/app/MyClass"' has no default export.


สิ่งนี้อาจช่วยได้: stackoverflow.com/q/32236163/218196
Felix Kling

3
อ่านบางเรื่องเบา ๆ ในหัวข้อ มันอาจช่วยถ้าคุณแสดงวิธีการนำเข้าคลาสนี้ฉันเชื่อว่าเป็นที่ที่เกิดข้อผิดพลาด (คุณอาจต้องแก้ไขไวยากรณ์การนำเข้าเพื่อแก้ไขสถานการณ์ข้อผิดพลาด)
Sunil D.

5
"ส่งออก" และ "ส่งออกเริ่มต้น" ไม่ใช่ TypeScript เลย - เป็น ES6
อาจารย์เจมส์

คำตอบ:


459

ส่งออกเริ่มต้น ( export default)

// MyClass.ts -- using default export
export default class MyClass { /* ... */ }

ข้อแตกต่างที่สำคัญคือคุณสามารถมีการส่งออกเริ่มต้นหนึ่งรายการต่อไฟล์เท่านั้นและคุณนำเข้าเช่น:

import MyClass from "./MyClass";

คุณสามารถตั้งชื่อใดก็ได้ตามต้องการ เช่นนี้ใช้งานได้ดี:

import MyClassAlias from "./MyClass";

ส่งออกที่มีชื่อ ( export)

// MyClass.ts -- using named exports
export class MyClass { /* ... */ }
export class MyOtherClass { /* ... */ }

เมื่อคุณใช้การส่งออกที่มีชื่อคุณสามารถมีหลายการส่งออกต่อไฟล์และคุณต้องนำเข้าการส่งออกที่ล้อมรอบด้วยวงเล็บปีกกา:

import { MyClass } from "./MyClass";

หมายเหตุ: การเพิ่มเครื่องหมายปีกกาจะแก้ไขข้อผิดพลาดที่คุณอธิบายไว้ในคำถามของคุณและชื่อที่ระบุในวงเล็บปีกกาจะต้องตรงกับชื่อของการส่งออก

หรือพูดว่าไฟล์ของคุณส่งออกหลายคลาสจากนั้นคุณสามารถนำเข้าทั้งสองอย่างดังนี้

import { MyClass, MyOtherClass } from "./MyClass";
// use MyClass and MyOtherClass

หรือคุณอาจให้ชื่อต่างกันในไฟล์นี้:

import { MyClass, MyOtherClass as MyOtherClassAlias } from "./MyClass";
// use MyClass and MyOtherClassAlias

หรือคุณสามารถนำเข้าทุกสิ่งที่ส่งออกโดยใช้* as:

import * as MyClasses from "./MyClass";
// use MyClasses.MyClass and MyClasses.MyOtherClass here

ต้องใช้อะไร

ใน ES6 การส่งออกเริ่มต้นรัดกุมเนื่องจากกรณีการใช้งานของพวกเขาเป็นเรื่องธรรมดามาก ; อย่างไรก็ตามเมื่อฉันทำงานเกี่ยวกับรหัสภายในโครงการใน TypeScript ฉันชอบที่จะใช้การส่งออกที่มีชื่อแทนการส่งออกเริ่มต้นเกือบตลอดเวลาเพราะมันทำงานได้ดีมากกับการปรับเปลี่ยนรหัส ตัวอย่างเช่นหากคุณส่งออกคลาสและเปลี่ยนชื่อคลาสนั้นจะเป็นการเปลี่ยนชื่อคลาสในไฟล์นั้นเท่านั้นไม่ใช่การอ้างอิงอื่นในไฟล์อื่น ด้วยการส่งออกที่มีชื่อมันจะเปลี่ยนชื่อคลาสและการอ้างอิงทั้งหมดไปยังคลาสนั้นในไฟล์อื่นทั้งหมด

นอกจากนี้ยังเล่นได้ดีมากกับไฟล์บาร์เรล (ไฟล์ที่ใช้การexport *ส่งออกเนมสเปซ- เพื่อส่งออกไฟล์อื่น ๆ ) ตัวอย่างนี้แสดงในส่วน "ตัวอย่าง" ของคำตอบนี้

โปรดทราบว่าความคิดเห็นของฉันเกี่ยวกับการใช้การส่งออกที่มีชื่อแม้ว่าจะมีการส่งออกเพียงรายการเดียวเท่านั้นซึ่งตรงกันข้ามกับคู่มือ TypeScript - ดูที่ส่วน "ธงแดง" ฉันเชื่อว่าคำแนะนำนี้ใช้ได้เฉพาะเมื่อคุณสร้าง API เพื่อให้ผู้อื่นใช้และรหัสไม่ได้อยู่ภายในโครงการของคุณ เมื่อฉันออกแบบ API import myLibraryDefaultExport from "my-library-name";สำหรับคนที่จะใช้ผมจะใช้การส่งออกเริ่มต้นเพื่อให้ผู้คนสามารถทำได้ หากคุณไม่เห็นด้วยกับฉันเกี่ยวกับการทำเช่นนี้ฉันชอบที่จะได้ยินเหตุผลของคุณ

ที่กล่าวว่าค้นหาสิ่งที่คุณต้องการ! คุณสามารถใช้อย่างใดอย่างหนึ่งอื่น ๆ หรือทั้งสองอย่างในเวลาเดียวกัน

คะแนนเพิ่มเติม

การส่งออกเริ่มต้นคือการส่งออกที่มีชื่อพร้อมชื่อdefaultดังนั้นหากไฟล์มีการส่งออกเริ่มต้นคุณสามารถนำเข้าโดยทำดังนี้

import { default as MyClass } from "./MyClass";

และรับทราบวิธีอื่น ๆ ในการนำเข้าที่มีอยู่: 

import MyDefaultExportedClass, { Class1, Class2 } from "./SomeFile";
import MyDefaultExportedClass, * as Classes from "./SomeFile";
import "./SomeFile"; // runs SomeFile.js without importing any exports

3
สิ่งที่เกิดขึ้นimport myAlias = require("./PathToFile")และมีexport = IInterfaceOrClassอยู่ในแฟ้ม? ตอนนี้เป็นแบบเก่าหรือไม่
BenCr

@BenCr ใช่นี่เป็นวิธี es6 ใหม่
David Sherret

ทำไมคุณไม่ให้ตัวอย่าง 'การส่งออกที่มีชื่อ'
Stato Machino

aws-sdk / clients / sns ไม่มีการส่งออกเริ่มต้นและเมื่อเข้าถึง sns โดยใช้การนำเข้า sns จาก '/ sns' ฉันไม่ได้รับการส่งออก แต่การนำเข้า myAlias ​​= ต้องการ ("./ PathToFile") ฉันจะทำบางอย่างเพื่อเปลี่ยนนำเข้า sns จาก '/ sns' โดยไม่ทำการเปลี่ยนแปลงที่มาได้ไหม
Jeson Dias

หากคุณไม่ใส่คำหลักอย่างชัดเจนdefaultจะยังคงมีการส่งออกเริ่มต้นอยู่ในไฟล์นั้นหรือไม่ ถ้าเป็นเช่นนั้นกฎคืออะไร
Simon_Weaver

10

ฉันพยายามแก้ไขปัญหาเดียวกัน แต่พบคำแนะนำที่น่าสนใจโดยBasarat Ali Syedจากชื่อเสียงของTypeScript Deep Diveว่าเราควรหลีกเลี่ยงการexport defaultประกาศทั่วไปสำหรับชั้นเรียนและต่อท้ายexportแท็กในการประกาศคลาสแทน คลาสที่อิมพอร์ตควรแสดงรายการแทนในimportคำสั่งของโมดูล

นั่นคือ: แทน

class Foo {
    // ...
}
export default Foo;

และง่ายimport Foo from './foo';ในโมดูลที่จะนำเข้าหนึ่งควรใช้

export class Foo {
    // ...
}

และimport {Foo} from './foo'ในผู้นำเข้า

เหตุผลที่เป็นปัญหาในการสร้างชั้นเรียนใหม่และงานเพิ่มเติมสำหรับการส่งออก โพสต์ต้นฉบับโดย Basarat อยู่ในexport defaultสามารถนำไปสู่ปัญหา


0

นี่คือตัวอย่างของการส่งออกวัตถุอย่างง่าย

var MyScreen = {

    /* ... */

    width : function (percent){

        return window.innerWidth / 100 * percent

    }

    height : function (percent){

        return window.innerHeight / 100 * percent

    }


};

export default MyScreen

ในไฟล์หลัก (ใช้เมื่อคุณไม่ต้องการและไม่จำเป็นต้องสร้างอินสแตนซ์ใหม่) และไม่ใช่ไฟล์ส่วนกลางคุณจะนำเข้าสิ่งนี้เมื่อจำเป็นเท่านั้น:

import MyScreen from "./module/screen";
console.log( MyScreen.width(100) );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.