12

What is the pattern for one class per file where multiple classes (and therefore multiple files) contribute to the same namespace? I'm asking this specifically in a Node.js context.

I know how to define one class per file in the same namespace:

foo/A.ts:

module foo {
    export class A {
    }
}

foo/B.ts:

module foo {
    export class B {
    }
}

main.ts:

/// <reference path="./foo/A.ts"/>
/// <reference path="./foo/B.ts"/>

// TODO: How do I import the foo namespace at runtime?

TypeScript is supposedly a language for application-scale JavaScript development, yet we seem to be left out in the cold on the most fundamental aspect of application-scale development, which is how to layout and structure code files and how everything is linked together at runtime.

4 Answers 4

8

In nodejs, each file is a module. When you are writing code for nodejs, using module (what typescript calls internal modules) is not required.

The foo in file A is actually A.foo, and the foo in file B is actually B.foo. This is the way nodejs works. Typescript is following what is conventional in nodejs.

More info on external vs. internal modules : http://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

PS regarding:

most fundamental aspect of application-scale development

It is fundamental in the browser, not in nodejs. There is no global scope in nodejs the way there is in the browser.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but I think saying that modules are not required in Node.js is missing the point of the question. I want to use namespaces and module is the TypeScript way to do that. If modules can't be used in Node.js, then TypeScript can't be used for "application-scale development" for Node.js. By "most fundamental aspect of application-scale development" I mean in general, as seen in languages like Java and C#, both of which have a namespace/package system that facilitates the most fundamental aspect of application-scale development.
I've seen this video before and watched it against just now. Thanks. I think you're onto something with using the --out option. I'll see how that works...
6

As basarat mentions, in Node.js, files are modules. The correct way to write the code you are working on is:

foo/A.ts:

class A {
}

export = A;

foo/B.ts:

class B {
}

export = B;

main.ts:

import A = require('./foo/A');
import B = require('./foo/B');

This is detailed in the Imports and Exports section of The Definitive Guide to TypeScript.

5 Comments

This does not answer the question asked. Feel free to delete.
How does this not answer the question? Your “namespace” foo is defined by the directory name. This is how Node.js works, and this is how AMD works. Just because you don’t currently understand the difference between internal and external modules doesn’t mean the answer is wrong…
It doesn't answer the question because I specifically asked how to achieve class-per-file with a namespace containing multiple classes and therefore a namespace being defined across multiple files.
I’m not sure how else I can explain this. What you want is not how modules work in Node.js. You are trying to wedge a square peg in a round hole. This is not how namespaces work in Node.js. You don’t do what you are doing if you are writing proper Node.js code. You should be using the pattern that basarat and I both described when you are “namespacing” code in Node.js, or AMD, or any other modern module system.
Achievement unlocked: Square peg placed into round hole. See my answer.
1

A bit late to the party, but I wrote a grunt plugin that lets you use the file-per-class/AMD style of programming in node and compile that code for both AMD (the browser) and CommonJS (node) while avoiding the use of client-side shims like requireJS.

https://www.npmjs.org/package/grunt-contrib-serverify-ts

It's a bit rough and ready at this stage, but it's working for me on a reasonably complex project.

2 Comments

+1 for interesting approach. But it is not IDE-friendly
@xmojmr works fine in my IDE (Visual Studio) which thinks that everything is an AMD module (had to rewrite some CommonJS d.ts files in the AMD style to fool it), but yes it's not particularly debugger, mapping-file, or stack-trace friendly :D.
0

This will work if all the TypeScript files are compiled to a single JavaScript file using the --out option. No further code is required. Without this option, main.js (from main.ts) will not see module foo and a ReferenceError will be thrown.

Thanks to Basarat for linking to one of his videos which recommends the --out option: http://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

1 Comment

Do not do this - this answer solves the author's module design which is itself a bastardization of the perfectly acceptable module system in node. It "works", but it is not proper. C Snover's answer is the right advice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.