ค้นหาเว็บไซต์

node.js - วิธีการออกแบบโมดูล API ใน TypeScript อย่างถูกต้อง?


ฉันต้องการออกแบบโมดูล TypeScript (2.7) สำหรับการเข้าถึงระบบภายนอก ให้เรียกมันว่า InfoSys ฉันใช้วิธีการดังต่อไปนี้

ฉันได้สร้าง info-sys.ts ซึ่งกำหนดคลาส API และอินเทอร์เฟซและเอนัมที่เกี่ยวข้อง เช่น:

class Api {
    constructor(private endpoint: Endpoint) {
        // ...
    }
}

enum Endpoint {
    CONTACTS = "contacts"
}

interface Contact {
    name: string;
}

ตอนนี้ฉันต้องการส่งออกทุกอย่างภายใต้ชื่อที่เฉพาะเจาะจง ดังนั้นฉันจึงเพิ่มคำสั่งส่งออก:

export const InfoSys = {
    Api,
    Endpoint,
    Contact
};

เมื่อฉันพยายามใช้โมดูลในไฟล์อื่น เช่น:

import { InfoSys } from "info-sys";

// this line throws error: "Cannot find namespace 'InfoSys'"
private api: InfoSys.Api;

// but this line is ok
api = new InfoSys.Api(InfoSys.Endpoint.CONTACTS);

วิธีการทำงานคือดังนี้ - เพื่อส่งออกแต่ละชิ้นแยกกัน:

export class Api {
    constructor(private endpoint: Endpoint) {
        // ...
    }
}

export enum Endpoint {
    CONTACTS = "contacts"
}

export interface Contact {
    name: string;
}

และนำเข้าทั้งหมดไปยังตัวแปรเดียว:

import * as InfoSys from "info-sys";

แต่ชื่อของตัวแปรสามารถเป็นอะไรก็ได้ มันไม่สำคัญต่อการทำงาน แต่ฉันต้องการบังคับให้ผู้พัฒนาที่จะใช้โมดูลระบบสารสนเทศนี้ ต้องใช้ชื่อเฉพาะเมื่อเข้าถึงมัน (เพื่อความง่ายในการอ่านและการดูแลรักษา) ควรออกแบบโมดูลนี้อย่างไรให้ถูกต้อง?

คำตอบ #1

คุณสามารถใช้ namespace ได้:

export namespace InfoSys {
  Api,
  Endpoint,
  Contact
};

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

ถ้า Api เป็นจุดเข้าหลักเพียงจุดเดียวสำหรับทั้งหมดนี้ ผมก็อยากจะแนะนำสิ่งนี้ด้วย:

export class InfoSysApi { ... }
export namespace InfoSysApi {
  export enum Endpoint = { ... }
  export interface Contact { ... }
}  

อัปเดต: เพื่อให้แน่ใจว่าฉันสื่อความหมายได้ชัดเจน อย่าทำสิ่งต่อไปนี้:

export namespace Foo {
  export function X() { return 'x' }
  export function Y() { return 'y' }
}

ใช้ export namespace สำหรับส่งออก "ประเภทที่ถูกดึงเข้า" เท่านั้น ไม่ใช่ค่าต่าง ๆ

ในคู่มือ TypeScript: https://www.typescriptlang.org/docs/handbook/declaration-merging.html

แม้ว่าตารางจะระบุว่าชื่อสเปซสามารถมีค่าได้ แต่ถือว่าเป็นแนวปฏิบัติที่ไม่ดีหากคุณกำลังเขียน ESM (import/export)

Namespace และ ESM เป็นกลไกสองแบบที่แตกต่างกันเพื่อให้ได้ผลลัพธ์ที่คล้ายกัน อย่าผสมพวกมันเข้าด้วยกัน