传输后访问TypeScript中已声明(且未导出)模块中的枚举
TL;DR 不导出名称空间,而只声明名称空间,我希望访问其中的枚举。一旦传输,名称空间就不可访问(它是一个未定义的对象),因此无法访问枚举(名称空间上有一个错误) 解释 我正在用TypesScript设置一个项目,我希望避免导入此项目特定的所有定义。在这段代码中,我创建了一个名称空间,在其中为我的redux逻辑放置本地定义 redux声明的摘录(redux.d.ts): 这允许我避免在所有代码中导入定义(例如,在传输后访问TypeScript中已声明(且未导出)模块中的枚举,typescript,Typescript,TL;DR 不导出名称空间,而只声明名称空间,我希望访问其中的枚举。一旦传输,名称空间就不可访问(它是一个未定义的对象),因此无法访问枚举(名称空间上有一个错误) 解释 我正在用TypesScript设置一个项目,我希望避免导入此项目特定的所有定义。在这段代码中,我创建了一个名称空间,在其中为我的redux逻辑放置本地定义 redux声明的摘录(redux.d.ts): 这允许我避免在所有代码中导入定义(例如,在const-mapStateToProps=(state:Redux.Store.D
const-mapStateToProps=(state:Redux.Store.Definition)=>state;
在我的顶级组件中,我不必导入任何Redux名称空间)
谈到这个问题,我写了这个reducer(corpusdreducer.ts extract):
传输后,我将得到错误ReferenceError:Redux没有为行定义,Redux.Actions.TypeKeys.CORPUS\u加载了
我怀疑Redux
在运行时不可用,因为命名空间属于TypeScript世界TypeKeys
,另一方面,它是一个枚举,应该在JavaScript中有一个映射,因此我的预期行为是,一旦传输,枚举仍然可以访问
如果我添加一个导出(将行更改为declare namespace Redux
),该文件将“升级”为一个模块,但是我需要在代码中的任何地方导入它
问题
如何访问枚举以避免export子句(从而在任何地方显式导入模块)?是否有我没有遵循的良好实践?枚举在运行时使用enum对象保存值。这意味着,如果这个对象不可访问,依赖于它存在的代码将在您发现时失败 最好的解决方案是确保导出该对象。添加一个保存枚举的额外模块并导入该模块 如果不可能,可以在声明中使用常量枚举。常量枚举不依赖于对象的存在,因为每当编译器遇到对枚举值的引用时,实际值将在生成的JS中硬编码
const enum TypeKeys { // No code for const enums is generated.
REDUX_INIT = '@@redux/INIT',
BOOTSTRAP = 'BOOTSTRAP',
CORPUS_LOADED = 'CORPUS_LOADED',
}
let d = TypeKeys.BOOTSTRAP; // All enum references are replaced with values, so this becomes var d = "BOOTSTRAP"
您应该注意这种方法,因为这意味着所有值都是在JS中硬编码的,对枚举的任何更改都需要您重新生成引用枚举的任何代码
编辑
适用于我的完整代码:
// definitions.d.ts
declare namespace Redux {
namespace Actions {
const enum TypeKeys {
REDUX_INIT = '@@redux/INIT',
BOOTSTRAP = 'BOOTSTRAP',
CORPUS_LOADED = 'CORPUS_LOADED',
}
interface Definition {
doSomething(): void;
}
interface ActionTypes {
type: TypeKeys
payload: any;
}
}
namespace Store {
class CorpusManagement {}
}
}
// usage.ts
/// <reference path="./definitions.d.ts" />
export default (state: Redux.Store.CorpusManagement, action: Redux.Actions.ActionTypes): Redux.Store.CorpusManagement => {
switch (action.type) {
case Redux.Actions.TypeKeys.CORPUS_LOADED:
return { corpus: action.payload };
default:
return state === undefined ? { corpus: { documents: [] } } : state;
}
};
//definitions.d.ts
声明命名空间重复{
命名空间操作{
常量枚举类型键{
REDUX_INIT='@@REDUX/INIT',
BOOTSTRAP='BOOTSTRAP',
语料库加载='语料库加载',
}
接口定义{
doSomething():无效;
}
接口操作类型{
类型:类型键
有效载荷:任何;
}
}
名称空间存储{
类主体管理{}
}
}
//用法
///
导出默认值(状态:Redux.Store.CorpusManagement,操作:Redux.Actions.ActionTypes):Redux.Store.CorpusManagement=>{
开关(动作类型){
已加载大小写Redux.Actions.TypeKeys.CORPUS\u:
返回{corpus:action.payload};
违约:
返回状态===未定义?{corpus:{documents:[]}}}:状态;
}
};
输出:
(...)
(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/// <reference path="./definitions.d.ts" />
exports.default = (state, action) => {
switch (action.type) {
case "CORPUS_LOADED" /* CORPUS_LOADED */:
return { corpus: action.payload };
default:
return state === undefined ? { corpus: { documents: [] } } : state;
}
};
});
(…)
(功能(需要、导出){
“严格使用”;
defineProperty(导出,“\uu esModule”{value:true});
///
exports.default=(状态、操作)=>{
开关(动作类型){
案例“语料库已加载”/*语料库已加载*/:
返回{corpus:action.payload};
违约:
返回状态===未定义?{corpus:{documents:[]}}}:状态;
}
};
});
我可以接受重建要求(此声明将是此项目的本地声明,并且是自包含的),但“const”不起作用:(此外,如果我添加“导入”子句,该文件将成为一个适当的模块,这将使我回到我想要避免的事情:导入所有项目中的所有声明files@pierpytom它不需要导入,也不需要命名空间中的导出就可以工作。你说的const
不起作用是什么意思enum?这就是js看起来的样子:function(e,t,n){“使用严格”;Object.defineProperty(t,“\uu esModule”,{value:!0}),t.default=function(e,t){switch(t.type){case-Redux.Actions.TypeKeys.CORPUS\u-LOADED:return{CORPUS:t.payload};默认值:return void 0==e?{corpus:{documents:[]}}}}:e}}}
枚举是一个常量,但保留在名称空间中。出于完整性考虑,问题似乎来自“declare”关键字。如果我声明命名空间Foo{const enum Bar{Hello='World'}
,然后尝试console.log(Foo.Bar.Hello);
甚至在同一个文件中(仅在导出默认值之后)。我发现当“transpileOnly”时会出现错误指定了选项,并且在“create react app ts”的许多依赖项中的一些依赖项中设置了标志,这太难检查了。我将移动到一个普通的网页,看看会发生什么,但我不明白为什么您的解决方案不起作用,谢谢!)
// definitions.d.ts
declare namespace Redux {
namespace Actions {
const enum TypeKeys {
REDUX_INIT = '@@redux/INIT',
BOOTSTRAP = 'BOOTSTRAP',
CORPUS_LOADED = 'CORPUS_LOADED',
}
interface Definition {
doSomething(): void;
}
interface ActionTypes {
type: TypeKeys
payload: any;
}
}
namespace Store {
class CorpusManagement {}
}
}
// usage.ts
/// <reference path="./definitions.d.ts" />
export default (state: Redux.Store.CorpusManagement, action: Redux.Actions.ActionTypes): Redux.Store.CorpusManagement => {
switch (action.type) {
case Redux.Actions.TypeKeys.CORPUS_LOADED:
return { corpus: action.payload };
default:
return state === undefined ? { corpus: { documents: [] } } : state;
}
};
(...)
(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/// <reference path="./definitions.d.ts" />
exports.default = (state, action) => {
switch (action.type) {
case "CORPUS_LOADED" /* CORPUS_LOADED */:
return { corpus: action.payload };
default:
return state === undefined ? { corpus: { documents: [] } } : state;
}
};
});