如何在 TypeScript 中正确设计 API 模块?
How to properly design API module in TypeScript?
我想设计一个TypeScript (2.7) 模块来访问外部IS,姑且称之为InfoSys。我使用了以下方法。
我创建了 info-sys.ts
,它定义了 API class 和相关的接口和枚举,例如:
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";
但变量名可以随便起。它对功能并不重要,但我想强制使用 info-sys 模块的开发人员在访问它时使用特定名称(以便于阅读和维护)。如何正确设计这样的模块?
您可以使用 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
导出 "tugged in types",不导出值。
在 TypeScript 手册中:https://www.typescriptlang.org/docs/handbook/declaration-merging.html
虽然 table 说命名空间可以包含值,但如果您正在编写 ESM (import/export),则认为这是不好的做法。
命名空间和 ESM 是实现相似结果的两种不同机制。
不要把它们混在一起。
我想设计一个TypeScript (2.7) 模块来访问外部IS,姑且称之为InfoSys。我使用了以下方法。
我创建了 info-sys.ts
,它定义了 API class 和相关的接口和枚举,例如:
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";
但变量名可以随便起。它对功能并不重要,但我想强制使用 info-sys 模块的开发人员在访问它时使用特定名称(以便于阅读和维护)。如何正确设计这样的模块?
您可以使用 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
导出 "tugged in types",不导出值。
在 TypeScript 手册中:https://www.typescriptlang.org/docs/handbook/declaration-merging.html
虽然 table 说命名空间可以包含值,但如果您正在编写 ESM (import/export),则认为这是不好的做法。
命名空间和 ESM 是实现相似结果的两种不同机制。 不要把它们混在一起。