node.js - ¿Cómo diseñar correctamente un módulo API en TypeScript?
Quiero diseñar un módulo de TypeScript (2.7) para acceder a sistemas externos de información, llamémoslo InfoSys. Usé el siguiente enfoque.
Creé info-sys.ts que define una clase API y las interfaces y enumeraciones relacionadas, como:
class Api {
constructor(private endpoint: Endpoint) {
// ...
}
}
enum Endpoint {
CONTACTS = "contacts"
}
interface Contact {
name: string;
}
Ahora quiero exportar todas las cosas bajo un nombre específico. Así que añadí la declaración de exportación:
export const InfoSys = {
Api,
Endpoint,
Contact
};
Cuando intento usar el módulo en otro archivo, como:
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);
La forma en que funciona es la siguiente: exportar cada pieza individualmente:
export class Api {
constructor(private endpoint: Endpoint) {
// ...
}
}
export enum Endpoint {
CONTACTS = "contacts"
}
export interface Contact {
name: string;
}
e impórtalos todos a una sola variable:
import * as InfoSys from "info-sys";
Pero el nombre de la variable puede ser cualquiera. No es crítico para la funcionalidad, pero quiero obligar a los desarrolladores, que usarán el módulo info-sys, a usar un nombre específico al acceder a él (para una mayor legibilidad y mantenibilidad). ¿Cómo diseñar correctamente dicho módulo?
Respuesta #1
Puedes usar namespace:
export namespace InfoSys {
Api,
Endpoint,
Contact
};
En general, este enfoque debe evitarse. Pero en tu caso, está bien ya que estás entregando cosas que están estrechamente relacionadas.
Si Api es el único punto de entrada a todo esto, también recomendaría lo siguiente:
export class InfoSysApi { ... }
export namespace InfoSysApi {
export enum Endpoint = { ... }
export interface Contact { ... }
}
ACTUALIZACIÓN: Para asegurarme de que quede claro, NO hagas lo siguiente:
export namespace Foo {
export function X() { return 'x' }
export function Y() { return 'y' }
}
Solo usa export namespace para exportar "tipos enganchados", no valores.
En el manual de TypeScript: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
Aunque la tabla dice que el namespace puede contener valores, se considera una mala práctica si estás escribiendo ESM (import/export).
Namespace y ESM son dos mecanismos diferentes para lograr un resultado similar. No los mezcles juntos.
