Casares
Casares

Reputation: 51

Pure Javascript Module Pattern in TypeScript to not mess up global scope

I have been working as a front-end developer in pure javascript for some time. I was used to the module pattern as you can see in the example below. Now I'm starting with TypeScript and it's impossible for me to get the same example pattern. The goal is to get a kind of namespace so as not to mess up the global reach. What is the best way to achieve the same goal in TypeScript? Thanks

var myModulePattern = (function(){
    // Private properties - more or less
        var 
            moduleName = "myModulePattern",
            moduleAuthor = "Bob"
        ;
    // Private Methods - more or less
        function sayModuleHello (){
            return "Module " + moduleName + " made by " + moduleAuthor;
        }

    return {
    // Public properties
        createYear : 2018,
    // Public Methods
        greeting: function(){
            console.log("Hi: "+sayModuleHello());
            
        }
    }
})();

// Exits an alone object literal, so is no possible create another instance of the "class"
// Really, this is like a namespace to not mess up the global scope
myModulePattern.greeting();
console.log(myModulePattern.createYear);

Upvotes: 2

Views: 1942

Answers (4)

Hame
Hame

Reputation: 544

In order to avoid default exports and import * as myModule from "./path", I use a method that resembles OP's original code

// myModule.ts
function somePrivateModuleFunction() {
  console.log("Private module function")
}

const somePrivateVariable = "A private variable";

export const myModule = {
  publicFunction: () => {
    somePrivateModuleFunction();
  },
  
  publicProperty: "public property" as const,
}

Then I use the module like this

// somewhere-else.ts
import { myModule } from "./path/to/myModule";

myModule.publicFunction();
console.log(myModule.publicProperty);

Upvotes: 0

please-rewrite
please-rewrite

Reputation: 27

TypeScript no longer recommends using namespaces and we should use the module pattern in modern TypeScript code.

"we recommended modules over namespaces in modern code."

https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html

// module.ts
const moduleName = 'myModule'
const moduleAuthor = 'Bob'
const sayHello = () => "Module " + moduleName + " made by " + moduleAuthor

const year = 2022
const greeting = () => `hi ${sayHello()}`

export default {year, greeting}
// somewhereElse.ts
import Module from './module'

Module.greeting()

Upvotes: 1

Bergi
Bergi

Reputation: 665554

This is exactly what namespaces are made for.

namespace MyModule {
    // Private variables
    const moduleName = "myModulePattern";
    const moduleAuthor = "Bob";

    // Private functions
    function sayModuleHello() {
        return "Module " + moduleName + " made by " + moduleAuthor;
    }

    // Public properties
    export var createYear = 2018;
    // Public Methods
    export function greeting() {
        console.log("Hi: "+sayModuleHello());
    }
}

MyModule.greeting();
console.log(MyModule.createYear);

You might also want to put the module in its own file, so that you don't need the namespace wrapper any more.

Upvotes: 2

Link1510
Link1510

Reputation: 111

I would suggest you use typescript classes, as described in the docu https://www.typescriptlang.org/docs/handbook/classes.html

class myClassPattern {
    private className: string;
    private classAuthor: string;

    constructor(name: string, author: string) {
        this.className = name;
        this.classAuthor = author;

    }
    private sayClassHello():string{
      return "Class " + this.className + " made by " + this.classAuthor;
    }
    public greeting() {
        console.log("Hi: "+ this.sayClassHello());
    }
}

let greeter = new myClassPattern("myClassName", "myName");
greeter.greeting();

Upvotes: -1

Related Questions