Typescript - 如何声明具有已知属性的匿名对象?
Posted
技术标签:
【中文标题】Typescript - 如何声明具有已知属性的匿名对象?【英文标题】:Typescript - How to declare anonymous object with known properties? 【发布时间】:2018-07-04 01:18:28 【问题描述】:在 JS 中,我的很多模块只是包装静态函数、枚举和属性的对象。例如,我有一个模块Debug
与此类似(我确实简化了它):
export default Debug =
// Current mode set, enum value from Modes. Setted outside of the module (see below).
mode : null,
// Enum of all possible modes
Modes :
DEV : 0,
PROD : 1,
,
// getter, checks if it's in production mode
get isInProdMode()
return Debug.mode === Debug.Modes.PROD;
,
// If the condition is met, it will throw an error in development mode, or just silently log a warning in production mode
assert : function(condition, message)
if (condiftion)
if (Debug.isInProdMode)
console.warn(message);
else
throw message;
// index.js
Debug.mode = Debug.Modes.DEV;
如何在 Typescript 中创建这样的匿名对象?使用枚举作为属性?还有一个getter函数?所有属性都是已知的。 我真的被困住了。
【问题讨论】:
此代码已经是有效的打字稿。你还需要它做什么? 【参考方案1】:我倾向于解决这些场景的方法是只为匿名对象的属性创建接口,然后为匿名对象创建接口:
enum Modes
DEV = 0,
PROD = 1,
interface IDebug
mode: Modes | null;
Modes: typeof Modes;
readonly isInProdMode: boolean;
assert: (condition: boolean, message: string) => void;
const Debug: IDebug =
mode: null,
Modes,
get isInProdMode()
return Debug.mode === Debug.Modes.PROD;
,
assert: (condition, message) =>
if (condition)
if (Debug.isInProdMode)
console.warn(message);
else
throw message;
,
;
export default Debug;
【讨论】:
const Debug: IDebug = Modes, // ...
我永远不会认为这是可能的。 Ô.Ô【参考方案2】:
我会说惯用的方法是使用命名空间。
namespace Debug
export enum Modes DEV, PROD
export var mode: Modes = Modes.DEV;
export function isInProdMode(): boolean
return mode === Modes.PROD;
export function assert(condition: boolean, message: string)
if (condition)
if (isInProdMode())
console.warn(message);
else
throw message;
export default Debug
但是,命名空间不支持 getter 和 setter,因此需要将 getter 转换为常规函数。
如果需要将此代码声明为对象,则可以先定义枚举,然后从对象中引用。
enum Modes DEV, PROD
const Debug =
mode: Modes = Modes.DEV,
get isInProdMode(): boolean
return Debug.mode === Modes.PROD;
,
assert(condition: boolean, message: string)
// ...
【讨论】:
请停止使用 TypeScript 命名空间。它们阻止您使用 ES6 模块导入。是时候把那段悲伤的历史抛在脑后了! @LarsGyrupBrinkNielsen 听起来您将命名导出与默认导出混为一谈,并将其归咎于命名空间。默认导出对象与默认导出命名空间有所有相同的问题。 或者,如果您确定,请随意阅读 TypeScript 编译器的源代码,它大量使用命名空间作为一项功能,并告诉他们不要使用它。它们仍然是创建作用域类型的重要构造。 我说的是能够使用import someStuff from './some-es6-module';
。如果您知道如何在具有命名空间的文件中执行此操作,请告诉我。从 ES6 模块访问命名空间的导出成员也是如此。
这是一个命名的导出,如果你像 OP 一样使用export default
,那么对于对象或命名空间是不可能的。【参考方案3】:
// index.js
import Debug from './debug';
Debug.mode = Debug.Modes.DEV;
console.log(Debug.isInProdMode);
// false
【讨论】:
我的问题是关于转换调试模块。 对不起,我好像没听懂你的意思。 转换是什么意思? 例如,使Modes
一个枚举。或者向assert
函数添加签名。我没能做到,因为它在一个匿名对象中,而不是在类声明中。但我从@pete 那里得到了答案。谢谢。以上是关于Typescript - 如何声明具有已知属性的匿名对象?的主要内容,如果未能解决你的问题,请参考以下文章
您如何定义具有键字符串索引但具有特定类型的已知键的 TypeScript 接口?