In JS, a lot of my modules are just objects that wrap static functions, enums and properties. For example, I've got a module Debug
which is similar to this (I really simplified it):
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;
How can I make an anonymous object like this in Typescript? With an Enum as property? And a getter function? All properties are known. I'm really stuck.
In JS, a lot of my modules are just objects that wrap static functions, enums and properties. For example, I've got a module Debug
which is similar to this (I really simplified it):
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;
How can I make an anonymous object like this in Typescript? With an Enum as property? And a getter function? All properties are known. I'm really stuck.
Share Improve this question edited Jan 25, 2018 at 7:04 Yairopro asked Jan 24, 2018 at 21:29 YairoproYairopro 10.4k7 gold badges47 silver badges54 bronze badges 1- 3 this code is already valid typescript. What else would you need it to do? – toskv Commented Jan 24, 2018 at 21:35
3 Answers
Reset to default 4The way I've tended to resolve these scenarios is to just make interfaces for the properties of the anonymous objects, and then interfaces for the anonymous objects:
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;
I would say that the idiomatic way would be to use namespaces.
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
However, namespaces don't support getters and setters, so that getter would need to be converted into a regular function.
If you need to declare this code as an object, then you could define the enum first, then reference in from the object.
enum Modes { DEV, PROD }
const Debug = {
mode: Modes = Modes.DEV,
get isInProdMode(): boolean {
return Debug.mode === Modes.PROD;
},
assert(condition: boolean, message: string) {
// ...
}
}
// index.js
import Debug from './debug';
Debug.mode = Debug.Modes.DEV;
console.log(Debug.isInProdMode);
// false