2

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);
Casares
  • 51
  • 5
  • 1
    Don't ES6 modules fulfill all your needs for modularisation? – Bergi Mar 13 '18 at 15:48
  • If someone craves a general TypeScript implementation of the Module Pattern (as described by Crockford), you can have a look at this: bit.ly/2J4kjNx – oligofren Nov 27 '20 at 15:23

3 Answers3

2

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.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Good answer. You can also do `export const createYear` rather than `var`. – James Monger Mar 14 '18 at 09:28
  • 1
    @JamesMonger Yeah, I thought about that, but the object property in the original code is mutable so I kept that. – Bergi Mar 14 '18 at 15:30
  • @Bergi, thank you so much for your answers. It's just i had been looking for. But my ts-lint makes a warning about namespace. Is the use of namespace deprecated or so? – Casares Mar 20 '18 at 15:12
  • @Casares I don't know. What does the warning say? – Bergi Mar 20 '18 at 15:21
  • @Bergi, it says: [ts-lint] 'namespace' and 'module' are disallowed (no-namespace. It is a rule in tslint.json configuration file for the linter in my dev environment (vs code). All works ok if i continue and ts is compiled and throws the addecuate js. My preocuppation is if namespaces are in this days considered good pract or it is deprecated pract in type script 2.7. Thanks – Casares Mar 20 '18 at 19:14
  • @Casares See the [rule docs](https://palantir.github.io/tslint/rules/no-namespace/) and [this question](https://stackoverflow.com/q/44202309/1048572) then. Basically it asks you to use a whole module file (with quite the same content as the `namespace {…}` block) to structure your code. But if for some reason you want an IIFE module (which you usually wouldn't in plain ES6 either), then `namespace` syntax is just the right thing. – Bergi Mar 20 '18 at 21:42
1

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()
-1

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();
Link1510
  • 101
  • 1
  • 8
  • Why do you recommend a `class`? The OP doesn't need multiple instances. – Bergi Mar 13 '18 at 15:48
  • That's a terrible advice. Classes are inferior in almost every way, except for memory savings when creating multiple instances of the same type. – oligofren Nov 25 '20 at 11:34