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