I am looking to create a Modules system within my Application. I'm unsure on how to implement the following:
Module 1
class SomethingModule {
}
export default SomethingModule;
Module 2
class SomethingElseModule {
}
export default SomethingElseModule;
Module Loader
class ModuleLoader {
load(module) {
// "module" could be "Something" which should create a
// new instance of "SomethingModule"
module = module + 'Module';
// Require and create an instance of "module"
}
}
export default ModuleLoader;
Main File
var ModuleLoader = require('./ModuleLoader');
var loader = new ModuleLoader();
loader.load('SomethingElse');
I'm pretty new to modularised JavaScript and have no idea if this is even possible/feasible. If not, is there a way of doing this you'd suggest without polluting the global namespace and referencing window[moduleName]?
If I understand well your problem, you can create a Map and load your module in there:
class ModuleLoader {
constructor() {
this._modules = new Map();
}
load(module) {
// you should check if the module exist in a good world to not get any error
// and probably adjust the path of what you are requiring
this._modules.set(module, new require(`${module}Module`));
}
getModuleByName(name) {
return this._modules.get(name);
}
}
Edit: To make it work with browserify, you will need to have this list of all the modules somewhere. You can create a separate file ModuleBag like this:
//moduleBag.js
import yourModule from './yourModule';
import yourSecondModule from './yourSecondModule';
var map = new Map();
map.set('yourModule', yourModule);
map.set('yourSecondModule', yourSecondModule);
export default class map;
//moduleLoader.js
import moduleBag from './moduleBag';
class ModuleLoader {
constructor() {
this._modules = new Map();
}
load(module) {
var mod = moduleBag.get(module);
this._modules.set(module, new mod());
}
getModuleByName(name) {
return this._modules.get(name);
}
}
or just put it in the same file.
With this, browserify will be able to load all the necessary files.
Related
How to include functions in namespace / module when don't have module?
example: I have a namespace:
namespace Java {}
in typescript, usually when we need a function in namespace or module, we add 'export':
namespace Java {
export function version() {
return "java8";
}
}
namespace JavaScript {
function JavaVer() {
return Java.version();
}
}
But if I set module to none:
// tsconfig
"module": "none",
If module is none, I cannot use import / export:
website/sourcecode/main.ts:17:21 - error TS1148: Cannot use imports, exports, or module augmentations when '--module' is 'none'.
17 export function version() {}
so what can I do?
image:
You can use a plain object:
TS Playground
const Java = {
version () {
return "java8";
},
};
const JavaScript = {
JavaVer () {
return Java.version();
},
};
const vJ = Java.version(); // string
const vJS = JavaScript.JavaVer(); // string
console.log(vJ === vJS); // true
It was answered in here: It's actually "can't have any imports or exports at the top level". Imports and exports inside namespaces are fine because they don't export anything from .ts file at runtime, and as long as file remains 'not a module' module=None works fine. Long explanation here
I'm trying to access a exported Cache into another file, but not having success.
Basically I've got two files:
cache.ts I'll expose only the part that meter
import Cache = require('node-cache');
const narrativeCache: Cache = New Cache();
protected setNarrativeCache(): void {
narrativeCache.set(123,'abc',0);
}
module.exports.narrativeCache = narrativeCache;
I want use this narrative in this other file:
module.ts
import { narrativeCache } from '../transport/cache.ts';
function test1(): void {
narrativeCache.get(123); //Error in here, it doesn't find this
}
Files tree:
src\transport\cache.ts
src\reader\module.ts
The error is because it doesn't find this narrativeCache.
The error was becausing of typescript export type:
Here's the solution
export const narrativeCache: Cache = new Cache();
index.js of imported npm module myLib
const Mod1 = require('./mod1');
const Mod2 = require('./mod2');
const Mod3 = require('./mod3');
module.exports = {
Mod1,
Mod2,
Mod3,
};
mod1.js
class Mod1 {
constructor(url) {
}
}
file using the above npm module
const Mod1 = require('myLib');
const instance = new Mod1();
This is throwing the following error when trying to run it:
const instance = new Mod1();
^
TypeError: Mod1 is not a constructor
How should I reference the class from a single import index.js so that I may be able to create an instance of the class?
There seems to be a slight mistake in your import, the actual import will be like:
const {Mod1} = require('myLib');
which will pull the class from the file and give it to you (ES6 feature)
you can also do it like:
const Mod1 = require('myLib').Mod1;
hope this helps.
Let's say I want to implement and use the following ts module. It's just a basic validator that validates a first name:
export namespace Validators
{
export class NameValidator
{
constructor()
{
}
FirstNameIsValid(firstName: string)
{
return firstName.length < 20;
}
}
}
What would be the correct way for me to implement the module above? Also, what would be the correct way for me to reference and use this module from my ng2 component? The following import statement doesn't work:
import { Validators.NameValidator } from './modules/name-validator';
The way I have done it in the past is to create a module
module Formatter{
export class SsnFormatter {
ssn: string;
constructor(unformattedSsn: string) {
this.ssn = unformattedSsn.replace(/(\d{3})(\d{2})(\d{4})/, '$1-$2-$3');
}
formatSsn() {
return this.ssn;
}
}
}
Then within the other typescript files call it as
let f = new Formatter.SsnFormatter('111111111');
console.log(f);
As long as your class is within the same module namespace you should be able to reference it directly.
This was from an angular 1.x project but the version of TS or angular should not matter this is typescript communicating between modules.
I've made some extensions to the Date prototype like:
interface Date {
YearsFromToday(): number;
}
Date.prototype.YearsFromToday = function (): number {
// implementation
}
I'm using the ionic2 tutorial --v2 template, which is a pretty standard layout - app.html, app.ts, app.module etc.
I was wondering if there was an easy way to have this declared globally. I'm not sure exactly where to put this in the project?
Put your monkey patch code in a file.
You might call it monkey-patch-date.ts, for example:
monkey-patch-date.ts
interface Date {
YearsFromToday(): number;
}
Date.prototype.yearsFromToday = function (): number {
// implementation
}
and then import it in main.ts or whatever your entry module is:
main.ts
import './monkey-patch-date';
Alternately. You can make it a module that exports its monkey-patcher if you want to be extra explicit to call out that you are doing something dangerous.
monkey-patch-date.ts
declare global {
interface Date {
yearsFromToday(): number;
}
}
export default function () {
Date.prototype.yearsFromToday = function (): number {
// implementation
};
}
And import it like
main.ts
import monkeyPatchDate from './monkey-patch-date';
monkeyPatchDate();
Another alternative, especially useful for library authors is to allow monkey-patching but not require it while still exposing the functionality.
Here is an example:
date-augmentations/index.ts
export function yearsFromToday(date: Date): number {
// implementation
}
date-augmentations/monkey-patch.ts
import {yearsFromToday} from './index';
declare global {
interface Date {
yearsFromToday(): number;
}
}
Date.prototype.yearsFromToday = function() {
return yearsFromToday(this);
}
Now a consumer can either monkey patch the Date prototype by running
import 'date-augmentations/monkey-patch';
Can access the functionality by the export without monkey patching anything
import {yearsFromToday} from 'date-augmentations';
const date = new Date('12-12-2023');
const yft = yearsFromToday(date);
console.log(yft); // prints 6