gpt4 book ai didi

typescript - 如何在同一命名空间中的多个文件上合并 typescript 接口(interface)

转载 作者:行者123 更新时间:2023-12-05 02:14:07 25 4
gpt4 key购买 nike

我试图重构一个笨重的配置接口(interface)/对象,方法是将它的各个部分分成单独的文件,放在 namespace 下,我巧妙地命名为 Config

文档讨论了 namespaces that span multiple filesdeclaration merging of interfaces ,但我似乎无法让他们一起工作。

src/config/index.ts

/// <reference path="./server.ts" />
import fs from 'fs';
import json5 from 'json5';

const _config = readConfig();

namespace Config {
export const config = _config;

export interface IConfig {
someGeneralProperty: {
// ...
}
}
}

function readConfig(): Config.IConfig {
return json5.parse(fs.readFileSync('./path/to/config.json', 'utf-8'));
}

function doSomeOtherStuff() {
// fails: Property 'server' does not exist on type 'IConfig'.
console.log(_config.server.host);
}

src/config/server.ts

/// <reference path="./index.ts" />

namespace Config {
export interface IConfig {
server: {
host: string;
port: number;
}
}
}

src/index.ts

// fails: Module '"./config"' has no exported member 'config'.
import { config } from './config';

// fails: Cannot use namespace 'Config' as a value.
// fails: Namespace 'Config' has no exported member 'config'.
import config = Config.config;

我已经尝试了多种导出方式,例如 export default Config;export namespace Config {...} 在每个 src/config/... 文件,将 export const config 更改为 export var config。在 src/config/index.ts 中,我尝试了 export * from './server'。似乎没有任何帮助。

我有一种感觉,我正在做这一切都是错误的。

奇怪的是,每个文件中命名空间内的接口(interface)都是从命名空间导出的,所以在 src/index.ts 中,我可以这样做:

import IConfig = Config.IConfig;

let c: IConfig;
console.log(c.server.host);

但我不能在 src/config/index.tssrc/config/server.ts 中这样做。

最佳答案

首先你应该自己决定,如果你想将 config 对象分配给模块范围(即 import/export)或者在全局范围内(即浏览器中的window,节点中的global)。

命名空间的主要目的是在全局范围内定义属性/值。正如您在链接中正确指出的那样,合并了同名命名空间 - 包括包含的内部成员,如 IConfig 接口(interface)。

事情是这样的:只有当包含 namespace 的文件是一个脚本(没有 import/export 的非模块文件时才会发生合并> 在顶层)。

src/config/index.ts 中,你有 import 语句,所以文件变成了一个模块,而 namespace Config 确实不会合并。相反,它是一个模块内部命名空间,它甚至不是 exported(参见文档中的 Needless NamespacingDo not use namespaces in modules)。 src/config/server.ts 中的 Config 命名空间形成了自己的全局命名空间(非模块文件),这就是为什么您仍然可以使用包含的 IConfig 类型。

总而言之,如果您想要全局配置(值和类型),请确保多文件部分命名空间的每个部分都在非模块文件中声明。如果要从模块导出配置(如果可行,首选方式!更好的封装,没有全局范围污染,“现代”方式),请继续阅读。

备选方案:在模块中导出配置

src/config/server.ts:

export interface ServerConfig {
server: {
host: string;
port: number;
}
}

// you could also read a server-specific config value here, export it
// and merge it with a separately read common config value in index.ts
// export serverConfig: ServerConfig = readServerConfig()

src/config/index.ts:

import { ServerConfig } from "./server"

interface CommonConfig {
someGeneralProperty: {
// ...
}
}

export type IConfig = CommonConfig & ServerConfig

export const config: IConfig = readConfig(); // whatever readConfig looks like

源/索引.ts:

import { config } from './config'; 

config.server;
config.someGeneralProperty

随意调整零件,你需要。希望对您有所帮助。

关于typescript - 如何在同一命名空间中的多个文件上合并 typescript 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54120356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com