ฉันจะใช้เนมสเปซกับโมดูลภายนอกของ TypeScript ได้อย่างไร


233

ฉันมีรหัส:

baseTypes.ts

export namespace Living.Things {
  export class Animal {
    move() { /* ... */ }
  }
  export class Plant {
    photosynthesize() { /* ... */ }
  }
}

dog.ts

import b = require('./baseTypes');

export namespace Living.Things {
  // Error, can't find name 'Animal', ??
  export class Dog extends Animal {
    woof() { }
  }
}

tree.ts

// Error, can't use the same name twice, ??
import b = require('./baseTypes');
import b = require('./dogs');

namespace Living.Things {
  // Why do I have to write b.Living.Things.Plant instead of b.Plant??
  class Tree extends b.Living.Things.Plant {

  }
}

นี่คือความสับสนมาก ฉันต้องการให้โมดูลภายนอกทุกชนิดมีส่วนร่วมในเนมสเปซเดียวกัน, Living.Things. มันดูเหมือนว่านี้ไม่ได้ทำงานเลย - ฉันไม่สามารถมองเห็นในAnimal dogs.tsผมต้องเขียนชื่อ namespace เต็มรูปแบบในb.Living.Things.Plant tree.tsไม่สามารถรวมวัตถุหลายรายการในเนมสเปซเดียวกันข้ามไฟล์ได้ ฉันจะทำสิ่งนี้ได้อย่างไร

คำตอบ:


860

Candy Cup คล้ายคลึง

เวอร์ชั่น 1: ถ้วยสำหรับขนมทุกชนิด

สมมติว่าคุณเขียนโค้ดบางอย่างเช่นนี้:

Mod1.ts

export namespace A {
    export class Twix { ... }
}

Mod2.ts

export namespace A {
    export class PeanutButterCup { ... }
}

Mod3.ts

export namespace A {
     export class KitKat { ... }
}

คุณได้สร้างการตั้งค่านี้: ป้อนคำอธิบายรูปภาพที่นี่

แต่ละโมดูล (กระดาษ) ได้รับถ้วยของตัวเองAชื่อ นี่ไร้ประโยชน์ - คุณไม่ได้จัดระเบียบขนมของคุณที่นี่จริง ๆคุณแค่เพิ่มขั้นตอนเพิ่มเติม (นำมันออกจากถ้วย) ระหว่างคุณกับขนม


รุ่น 2: หนึ่งถ้วยในขอบเขตส่วนกลาง

หากคุณไม่ได้ใช้โมดูลคุณอาจเขียนโค้ดแบบนี้ (สังเกตการขาดการexportประกาศ):

global1.ts

namespace A {
    export class Twix { ... }
}

global2.ts

namespace A {
    export class PeanutButterCup { ... }
}

global3.ts

namespace A {
     export class KitKat { ... }
}

รหัสนี้สร้าง namespace ที่ผสานAในขอบเขตส่วนกลาง:

ป้อนคำอธิบายรูปภาพที่นี่

การตั้งค่านี้มีประโยชน์ แต่ไม่ได้นำไปใช้ในกรณีของโมดูล (เนื่องจากโมดูลจะไม่สร้างมลภาวะระดับโลก)


เวอร์ชัน 3: ไร้ความหมาย

จะกลับไปเช่นเดิมถ้วยA, AและAไม่ได้ทำคุณโปรดปรานใด ๆ แต่คุณสามารถเขียนรหัสเป็น:

Mod1.ts

export class Twix { ... }

Mod2.ts

export class PeanutButterCup { ... }

Mod3.ts

export class KitKat { ... }

เพื่อสร้างรูปภาพที่มีลักษณะดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ดีกว่ามาก!

ตอนนี้ถ้าคุณยังคิดอยู่ว่าคุณต้องการใช้เนมสเปซกับโมดูลของคุณมากเพียงใดอ่านต่อ ...


นี่ไม่ใช่แนวคิดที่คุณต้องการ

เราต้องย้อนกลับไปที่จุดเริ่มต้นว่าทำไมเนมสเปซมีอยู่ตั้งแต่แรกและตรวจสอบว่าเหตุผลเหล่านั้นสมเหตุสมผลสำหรับโมดูลภายนอกหรือไม่

องค์กร : เนมสเปซมีประโยชน์สำหรับการจัดกลุ่มวัตถุและประเภทที่เกี่ยวข้องกับเหตุผล ยกตัวอย่างเช่นใน C # System.Collectionsคุณกำลังจะไปหาทุกประเภทคอลเลกชันใน ด้วยการจัดระเบียบประเภทของเราเป็นเนมสเปซแบบลำดับขั้นเราจะมอบประสบการณ์ "การค้นพบ" ที่ดีสำหรับผู้ใช้ประเภทเหล่านั้น

ความขัดแย้งของชื่อ : เนมสเปซมีความสำคัญเพื่อหลีกเลี่ยงการชนกันของชื่อ ตัวอย่างเช่นคุณอาจมีMy.Application.Customer.AddFormและMy.Application.Order.AddForm- สองประเภทที่มีชื่อเหมือนกัน แต่เป็นชื่อเฉพาะที่แตกต่างกัน ในภาษาที่มีตัวระบุทั้งหมดอยู่ในขอบเขตรูทเดียวกันและแอสเซมบลีทั้งหมดโหลดทุกประเภทสิ่งสำคัญคือต้องมีทุกอย่างในเนมสเปซ

เหตุผลเหล่านั้นสมเหตุสมผลในโมดูลภายนอกหรือไม่

องค์กร : มีโมดูลภายนอกอยู่ในระบบไฟล์อยู่แล้วจำเป็นต้องมี เราต้องแก้ไขมันด้วยพา ธ และชื่อไฟล์ดังนั้นจึงมีรูปแบบองค์กรที่เป็นตรรกะเพื่อให้เราใช้ เราสามารถมี/collections/generic/โฟลเดอร์ที่มีlistโมดูลอยู่ในนั้น

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


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

กล่องในกล่องในกล่อง

เรื่องราว:

บ๊อบเพื่อนของคุณโทรหาคุณ "ฉันมีรูปแบบองค์กรใหม่ที่ยอดเยี่ยมในบ้านของฉัน" เขาพูด "ลองดูสิ!" ไม่เป็นไรลองดูว่าบ็อบมากับอะไรกัน

คุณเริ่มต้นในห้องครัวและเปิดตู้กับข้าว มี 60 กล่องแตกต่างกันแต่ละป้าย "ตู้กับข้าว" คุณเลือกกล่องโดยการสุ่มและเปิด ข้างในเป็นกล่องเดียวเขียนว่า "ธัญพืช" คุณเปิดกล่อง "Grains" และค้นหากล่องเดียวที่ชื่อ "พาสต้า" คุณเปิดกล่อง "พาสต้า" และค้นหากล่องเดียวที่ระบุว่า "Penne" คุณเปิดกล่องนี้และค้นหาพาสต้าเพนเน่หนึ่งถุงอย่างที่คุณคาดไว้

สับสนเล็กน้อยคุณหยิบกล่องที่อยู่ติดกันชื่อ "ครัว" ข้างในเป็นกล่องเดียวป้าย "Grains" อีกครั้ง คุณเปิดกล่อง "ธัญพืช" และค้นหากล่องเดียวที่มีป้ายกำกับ "พาสต้า" อีกครั้ง คุณเปิดกล่อง "พาสต้า" และค้นหากล่องเดียวกล่องนี้มีชื่อว่า "Rigatoni" คุณเปิดกล่องนี้และพบ ... พาสต้า rigatoni

"มันเยี่ยมมาก!" บ๊อบบอกว่า "ทุกอย่างอยู่ในเนมสเปซ!"

"แต่บ๊อบ ... " คุณตอบกลับ "รูปแบบองค์กรของคุณไร้ประโยชน์คุณต้องเปิดกล่องหลายอย่างเพื่อไปทำอะไรและมันไม่สะดวกกว่าที่จะหาอะไรมากกว่าที่คุณเพิ่งใส่ทุกอย่างไว้ในกล่องเดียวแทนที่จะเป็นสามกล่องอันที่จริงแล้วตั้งแต่ของคุณ ตู้เก็บอาหารนั้นถูกจัดเรียงตามชั้นวางแล้วโดยที่คุณไม่ต้องใช้กล่องเลยทำไมไม่ลองวางพาสต้าไว้บนชั้นแล้วหยิบมันขึ้นมาเมื่อคุณต้องการ "

"คุณไม่เข้าใจ - ฉันต้องตรวจสอบให้แน่ใจว่าไม่มีใครใส่อะไรที่ไม่ได้อยู่ในเนมสเปซ 'Pantry' และฉันได้จัดระเบียบพาสต้าทั้งหมดของฉันไว้ในPantry.Grains.Pastaเนมสเปซอย่างปลอดภัยแล้ว

บ๊อบเป็นคนสับสนมาก

โมดูลเป็นกล่องของตัวเอง

คุณอาจมีสิ่งที่คล้ายกันเกิดขึ้นในชีวิตจริง: คุณสั่งบางสิ่งใน Amazon และแต่ละรายการจะแสดงในกล่องของตัวเองโดยมีกล่องเล็ก ๆ อยู่ข้างในโดยที่รายการของคุณห่อด้วยบรรจุภัณฑ์ของตัวเอง แม้ว่ากล่องภายในจะคล้ายกัน แต่การจัดส่งจะไม่รวมกันอย่างเป็นประโยชน์

ไปกับกล่องเปรียบเทียบที่สังเกตที่สำคัญคือโมดูลภายนอกช่องของตัวเอง มันอาจเป็นไอเท็มที่ซับซ้อนมากที่มีฟังก์ชั่นมากมาย แต่โมดูลภายนอกที่ให้นั้นเป็นกล่องของมันเอง


คำแนะนำสำหรับโมดูลภายนอก

ตอนนี้เราได้รู้แล้วว่าเราไม่จำเป็นต้องใช้ 'namespaces' เราจะจัดการโมดูลของเราอย่างไร? หลักการและตัวอย่างที่ชี้นำบางประการปฏิบัติตาม

ส่งออกใกล้เคียงกับระดับสูงสุดเท่าที่จะทำได้

  • หากคุณส่งออกคลาสหรือฟังก์ชันเดียวให้ใช้export default:

MyClass.ts

export default class SomeType {
  constructor() { ... }
}

MyFunc.ts

function getThing() { return 'thing'; }
export default getThing;

การบริโภค

import t from './MyClass';
import f from './MyFunc';
var x = new t();
console.log(f());

นี่คือที่ดีที่สุดสำหรับผู้บริโภค พวกเขาสามารถตั้งชื่อประเภทของคุณตามที่พวกเขาต้องการ ( tในกรณีนี้) และไม่จำเป็นต้องทำสิ่งต่าง ๆ เพื่อค้นหาวัตถุของคุณ

  • หากคุณกำลังส่งออกวัตถุหลายรายการให้วางทั้งหมดไว้ที่ระดับบนสุด:

MyThings.ts

export class SomeType { ... }
export function someFunc() { ... }

การบริโภค

import * as m from './MyThings';
var x = new m.SomeType();
var y = m.someFunc();
  • หากคุณกำลังส่งออกสิ่งต่าง ๆ จำนวนมากคุณควรใช้คำหลักmodule/namespace

MyLargeModule.ts

export namespace Animals {
  export class Dog { ... }
  export class Cat { ... }
}
export namespace Plants {
  export class Tree { ... }
}

การบริโภค

import { Animals, Plants} from './MyLargeModule';
var x = new Animals.Dog();

ธงแดง

ทั้งหมดต่อไปนี้เป็นธงสีแดงสำหรับการสร้างโมดูล ตรวจสอบอีกครั้งว่าคุณไม่ได้พยายามกำหนด namespace ให้กับโมดูลภายนอกของคุณหากสิ่งเหล่านี้มีผลกับไฟล์ของคุณ:

  • ไฟล์ที่มีการประกาศระดับบนสุดเท่านั้นexport module Foo { ... }(ลบFooและย้ายระดับขึ้นทุกสิ่ง 'ขึ้น')
  • ไฟล์ที่มีไฟล์เดียวexport classหรือexport functionไม่มีเลยexport default
  • หลายไฟล์ที่เหมือนกันexport module Foo {ที่ระดับบนสุด (อย่าคิดว่าไฟล์เหล่านี้จะรวมกันเป็นหนึ่งเดียวFoo!)

80
นี่ไม่ใช่คำตอบ หลักฐานที่คุณไม่ต้องการหรือต้องการเนมสเปซสำหรับโมดูลภายนอกนั้นเป็นข้อผิดพลาด ในขณะที่ระบบไฟล์เป็นประเภทของโครงการองค์กรคุณสามารถนะใช้เพื่อวัตถุประสงค์เหล่านี้ก็ไม่ได้เกือบเป็นที่ดีสำหรับผู้บริโภคที่จะมี n งบนำเข้าเพื่อใช้คลาส n หรือฟังก์ชั่นจากโครงการรับ; โดยเฉพาะอย่างยิ่งเนื่องจากมันยังทำให้การกำหนดการตั้งชื่อเป็น muddies เมื่อคุณไม่ได้ใช้รหัสจริง
Albinofrenchy

12
เรื่องเท่าใดหนึ่งอาจต้องการมันไม่มีก็ยังคงเป็นไปไม่ได้
Ryan Cavanaugh

26
ฉันไม่เข้าใจเราไม่ได้เขียนปาสกาลอีกต่อไป ตั้งแต่เมื่อมีการจัดระเบียบโดยใช้ระบบไฟล์วิธีที่จะไป?
David

9
คุณสามารถทำได้โดยมีโมดูล "wrapper" ที่นำเข้าและส่งออกทุกสิ่งที่น่าสนใจแก่ผู้บริโภคห้องสมุดของคุณ แต่อีกครั้งการใช้ "namespace" จะไม่ให้ค่าใด ๆ นอกเหนือจากการบังคับให้มีการเปลี่ยนทิศทางในระดับอื่นสำหรับผู้ใช้รหัสของคุณ
Ryan Cavanaugh

13
ขอบคุณมากนะ ฉันรู้สึกว่าคุณควรเชื่อมโยงกับสิ่งนี้จาก www.typescriptlang.org/docs/handbook/namespaces.html ฉันต้องอ่านแล้วว่า typescriptlang.org ลิงค์ 3 หรือ 4 ครั้งและเป็น C # dev ฉันต้องการใส่ทุกอย่างในเนมสเปซ ฉันได้อ่านคำแนะนำที่บอกว่าไม่ แต่ไม่มีคำอธิบายว่าทำไมและไม่มีอะไรที่ชัดเจน (และอธิบายอย่างดี) เช่นนี้ ไม่มีอะไรในเอกสาร typescript ที่กล่าวถึง AFAIK นี้
Adam Plocher

53

ไม่มีอะไรผิดปกติกับคำตอบของไรอัน แต่สำหรับคนที่มาที่นี่เพื่อค้นหาวิธีการดูแลโครงสร้างแบบหนึ่งต่อไฟล์ในขณะที่ยังคงใช้เนมสเปซ ES6 อย่างถูกต้องโปรดอ้างอิงทรัพยากรที่มีประโยชน์นี้จาก Microsoft

สิ่งหนึ่งที่ไม่ชัดเจนกับผมหลังจากที่ได้อ่านเอกสารคือวิธีที่จะนำเข้าทั้งหมด (รวม) โมดูลที่มีเพียงครั้งเดียว import

แก้ไขวง กลับเพื่ออัปเดตคำตอบนี้ มีสองสามวิธีในการกำหนดเนมที่มีอยู่ใน TS

คลาสโมดูลทั้งหมดในไฟล์เดียว

export namespace Shapes {
    export class Triangle {}
    export class Square {}      
}

นำเข้าไฟล์ลงใน namespace และกำหนดใหม่

import { Triangle as _Triangle } from './triangle';
import { Square as _Square } from './square';

export namespace Shapes {
  export const Triangle = _Triangle;
  export const Square = _Square;
}

บาร์เรล

// ./shapes/index.ts
export { Triangle } from './triangle';
export { Square } from './square';

// in importing file:
import * as Shapes from './shapes/index.ts';
// by node module convention, you can ignore '/index.ts':
import * as Shapes from './shapes';
let myTriangle = new Shapes.Triangle();

การพิจารณาขั้นสุดท้าย คุณสามารถเนมสเปซแต่ละไฟล์ได้

// triangle.ts
export namespace Shapes {
    export class Triangle {}
}

// square.ts
export namespace Shapes {
    export class Square {}
}

แต่เมื่อมีการนำเข้าสองคลาสจากเนมสเปซเดียวกัน TS จะบ่นว่ามีตัวระบุซ้ำกัน ทางออกเดียวที่เป็นในเวลานี้คือการตั้งชื่อแทน

import { Shapes } from './square';
import { Shapes as _Shapes } from './triangle';

// ugh
let myTriangle = new _Shapes.Shapes.Triangle();

นามแฝงนี้น่ารังเกียจอย่างยิ่งดังนั้นอย่าทำเช่นนั้น คุณดีกว่าด้วยวิธีการข้างต้น ส่วนตัวฉันชอบ 'บาร์เรล'


6
"เนมสเปซ ES6" คืออะไร?
Aluan Haddad

@AluanHaddad เมื่อนำเข้า es2015 + สิ่งที่นำเข้าเป็นค่าเริ่มต้น destructured หรือเนมสเปซ const fs = require('fs'), fsคือการ namespace import * as moment from 'moment', momentคือการ namespace นี่คือภววิทยาไม่ใช่สเปค
Jefftopia

ฉันรู้ว่า แต่คุณควรอธิบายให้ดีในคำตอบของคุณ อย่างไรก็ตามเนมสเปซ ES6 นั้นเป็นเรื่องจริงและrequireตัวอย่างไม่สามารถใช้ได้กับเหตุผลหลายประการรวมถึงอาจไม่สามารถเรียกเนมสเปซ ES6 ได้ในขณะที่requireส่งคืนวัตถุธรรมดาซึ่งอาจเรียกได้
Aluan Haddad

1
ฉันไม่ทำตามเพราะไม่ว่าสิ่งที่นำเข้าจะเรียกได้หรือไม่มันยังทำหน้าที่เป็น namespace พูดอย่างมีเหตุผล ฉันไม่คิดว่าคำเตือนเป็นสาระสำคัญสำหรับคำตอบของฉันข้างต้น
Jefftopia

7

ลองจัดระเบียบตามโฟลเดอร์:

baseTypes.ts

export class Animal {
    move() { /* ... */ }
}

export class Plant {
    photosynthesize() { /* ... */ }
}

dog.ts

import b = require('./baseTypes');

export class Dog extends b.Animal {
    woof() { }
}   

tree.ts

import b = require('./baseTypes');

class Tree extends b.Plant {
}

LivingThings.ts

import dog = require('./dog')
import tree = require('./tree')

export = {
    dog: dog,
    tree: tree
}

main.ts

import LivingThings = require('./LivingThings');
console.log(LivingThings.Tree)
console.log(LivingThings.Dog)

แนวคิดก็คือโมดูลของคุณไม่ควรสนใจ / รู้ว่าพวกเขามีส่วนร่วมในเนมสเปซ แต่นี่จะทำให้ API ของคุณไปสู่ผู้บริโภคในรูปแบบที่กะทัดรัดและสมเหตุสมผลซึ่งไม่เชื่อเรื่องระบบโมดูลที่คุณใช้สำหรับโครงการ


8
LivingThings.dog.Dog คือสิ่งที่คุณมีที่นี่
Corey Alix

ฉันขอแนะนำให้รักษาตัวอักษรให้ตรงกันถ้าคุณส่งออก "ต้นไม้" จากนั้นนำเข้า "ต้นไม้" ไม่ใช่ "ต้นไม้"
demisx

1
นอกจากนี้คุณจะนำเข้าสิ่งใดจากtree.tsเมื่อไม่มีสมาชิกที่ส่งออกได้อย่างไร
demisx

แมนทีเอสมั่นใจว่ามีไวยากรณ์เก่า ๆ ที่โง่เขลาเหมือนกันimportและrequireอยู่ในคำสั่งเดียว
แอนดี้

3

การตอบคำถามเล็ก ๆ น้อย ๆ ของ Albinofrenchy:

base.ts

export class Animal {
move() { /* ... */ }
}

export class Plant {
  photosynthesize() { /* ... */ }
}

dog.ts

import * as b from './base';

export class Dog extends b.Animal {
   woof() { }
} 

things.ts

import { Dog } from './dog'

namespace things {
  export const dog = Dog;
}

export = things;

main.ts

import * as things from './things';

console.log(things.dog);

2
ขอบคุณสำหรับสิ่งนี้! เพียงแค่อยากจะบอกว่าการเปลี่ยนแปลงคำตอบที่มีอยู่ไม่ควรโพสต์เป็นคำตอบใหม่: ควรเพิ่มพวกเขาเป็นความคิดเห็นของคำตอบที่มีอยู่หรือควรแนะนำ (ดีกว่า) โดยแนะนำการแก้ไขคำตอบที่คุณต้องการ ทำให้ดีขึ้น.
a3nm

3

OP ฉันอยู่กับคุณผู้ชาย อีกครั้งด้วยไม่มีอะไรผิดปกติกับคำตอบนั้นด้วยคะแนน 300+ ขึ้นไป แต่ความคิดเห็นของฉันคือ:

  1. มีอะไรผิดปกติกับการใส่ชั้นเรียนลงในไฟล์ของตัวเองอบอุ่นเป็นรายบุคคล? ฉันหมายความว่าสิ่งนี้จะทำให้สิ่งต่าง ๆ ดูดีขึ้นใช่มั้ย (หรือบางคนเช่นเดียวกับไฟล์บรรทัด 1,000 สำหรับทุกรุ่น)

  2. ดังนั้นถ้าสำเร็จแรกเราจะต้องนำเข้านำเข้านำเข้า ... นำเข้าเฉพาะในแต่ละรูปแบบไฟล์เช่น man, srsly, ไฟล์รูปแบบ, ไฟล์. d.ts ทำไมมีจำนวนมาก * อยู่ในนั้น? มันควรจะง่ายเรียบง่ายและเป็นระเบียบ ทำไมฉันต้องนำเข้าที่นั่น? ทำไม? C # มีเนมสเปซด้วยเหตุผล

  3. และจากนั้นคุณใช้อักษร "filenames.ts" เป็นตัวระบุอย่างแท้จริง ในฐานะตัวบ่งชี้ ... มาปี 2017 ตอนนี้และเรายังทำเช่นนั้น? ฉันกลับไปที่ดาวอังคารและนอนหลับต่อไปอีก 1,000 ปี

น่าเศร้าที่คำตอบของฉันคือ: ไม่คุณไม่สามารถทำให้ "namespace" ทำงานได้หากคุณไม่ได้ใช้การนำเข้าทั้งหมดหรือใช้ชื่อไฟล์เหล่านั้นเป็นตัวระบุ (ซึ่งฉันคิดว่ามันโง่จริงๆ) อีกทางเลือกหนึ่งคือ: ใส่การอ้างอิงทั้งหมดเหล่านั้นลงในกล่องที่เรียกว่า filenameasidentifier.ts และใช้

export namespace(or module) boxInBox {} .

ล้อมรอบพวกเขาดังนั้นพวกเขาจะไม่พยายามเข้าถึงชั้นเรียนอื่นที่มีชื่อเดียวกันเมื่อพวกเขาเพียงแค่พยายามรับการอ้างอิงจากชั้นเรียนนั่งอยู่ด้านบนของพวกเขา


3

คำถาม / ความคิดเห็นหลายข้อที่ฉันเคยเห็นรอบ ๆ เรื่องนี้ทำให้ฉันฟังราวกับว่าคน ๆ นั้นกำลังใช้คำNamespaceว่าโมดูลแทนนามแฝง ดังที่ Ryan Cavanaugh พูดถึงในความคิดเห็นของเขาคุณสามารถมีโมดูล 'Wrapper' ส่งออกโมดูลอีกหลายโมดูล

ถ้าคุณอยากที่จะนำเข้ามันทั้งหมดมาจากที่เดียวกันชื่อโมดูล / tsconfig.jsonนามแฝงรวมโมดูลเสื้อคลุมที่มีการทำแผนที่เส้นทางในของคุณ

ตัวอย่าง:

./path/to/CompanyName.Products/Foo.ts

export class Foo {
    ...
}


./path/to/CompanyName.Products/Bar.ts

export class Bar {
    ...
}


./path/to/CompanyName.Products/index.ts

export { Foo } from './Foo';
export { Bar } from './Bar';



tsconfig.json

{
    "compilerOptions": {
        ...
        paths: {
            ...
            "CompanyName.Products": ["./path/to/CompanyName.Products/index"],
            ...
        }
        ...
    }
    ...
}



main.ts

import { Foo, Bar } from 'CompanyName.Products'

หมายเหตุ : ความละเอียดของโมดูลในไฟล์. js ที่ส่งออกจะต้องได้รับการจัดการอย่างใดเช่นhttps://github.com/tleunen/babel-plugin-module-resolverนี้

ตัวอย่าง.babelrcการจัดการการแก้ไขนามแฝง:

{
    "plugins": [
        [ "module-resolver", {
            "cwd": "babelrc",
            "alias": {
                "CompanyName.Products": "./path/to/typescript/build/output/CompanyName.Products/index.js"
            }
        }],
        ... other plugins ...
    ]
}

1

ลองใช้โมดูลเนมสเปซนี้

namespaceModuleFile.ts

export namespace Bookname{
export class Snows{
    name:any;
    constructor(bookname){
        console.log(bookname);
    }
}
export class Adventure{
    name:any;
    constructor(bookname){
        console.log(bookname);
    }
}
}





export namespace TreeList{
export class MangoTree{
    name:any;
    constructor(treeName){
        console.log(treeName);
    }
}
export class GuvavaTree{
    name:any;
    constructor(treeName){
        console.log(treeName);
    }
}
}

bookTreeCombine.ts

--- ส่วนที่รวบรวม ---

import {Bookname , TreeList} from './namespaceModule';
import b = require('./namespaceModule');
let BooknameLists = new Bookname.Adventure('Pirate treasure');
BooknameLists = new Bookname.Snows('ways to write a book'); 
const TreeLis = new TreeList.MangoTree('trees present in nature');
const TreeLists = new TreeList.GuvavaTree('trees are the celebraties');

0

dog.ts

import b = require('./baseTypes');

export module Living.Things {
    // Error, can't find name 'Animal', ??
    // Solved: can find, if properly referenced; exporting modules is useless, anyhow
    export class Dog extends b.Living.Things.Animal {
        public woof(): void {
            return;
        }
    }
}

tree.ts

// Error, can't use the same name twice, ??
// Solved: cannot declare let or const variable twice in same scope either: just use a different name
import b = require('./baseTypes');
import d = require('./dog');

module Living.Things {
    // Why do I have to write b.Living.Things.Plant instead of b.Plant??
    class Tree extends b.Living.Things.Plant {
    }
}

-1

วิธีที่เหมาะสมในการจัดระเบียบรหัสของคุณคือการใช้ไดเรกทอรีแยกต่างหากแทนเนมสเปซ แต่ละคลาสจะอยู่ในไฟล์ของตัวเองในโฟลเดอร์เนมสเปซที่เกี่ยวข้อง index.ts จะส่งออกแต่ละไฟล์อีกครั้งเท่านั้น ไม่ควรมีรหัสจริงในไฟล์ index.ts การจัดระเบียบรหัสของคุณเช่นนี้ทำให้การนำทางได้ง่ายขึ้นและจัดทำเอกสารด้วยตนเองตามโครงสร้างไดเรกทอรี

// index.ts
import * as greeter from './greeter';
import * as somethingElse from './somethingElse';

export {greeter, somethingElse};

// greeter/index.ts
export * from './greetings.js';
...

// greeter/greetings.ts
export const helloWorld = "Hello World";

จากนั้นคุณจะใช้มันเช่น:

import { greeter } from 'your-package'; //Import it like normal, be it from an NPM module or from a directory.
// You can also use the following syntax, if you prefer:
import * as package from 'your-package';

console.log(greeter.helloWorld);

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