3

The story

I am building a modular library for math operations. I also want to divide the library into multiple modules : core, relational, vectors, and so on. The modules can be used on their own (but all depend on the core module)

  1. I know it's not possible to use partial classes How do I split a TypeScript class into multiple files? / https://github.com/Microsoft/TypeScript/issues/563

The problem :

The core module defines the Set class, which is a mathematical set. It defines operations such as Set#add, Set#remove.

Though, the optional relational module adds a Set#productoperator on the Setclass.

Other modules could also add other operations on the Set class. I want to keep the possibility of adding functionality when I will see fit.

The question

  1. With typescript, how can I add a method on a class that resides in another module ?

  2. How can I arrange the typings so that the user of my library will see the Set#product in his code completion only if he installed the relational module ? Otherwise he only sees the #add and #remove operations ?

I am developing this library for node.js, but also use browserify to bundle it for browser use.

// core/set.ts 

export class Set {
  add(element){}
  remove(element){}
}


// relational/set.ts

import {Set} from './../core/set.ts';

Set.prototype.product = function(){} // ?


// app/index.js

import {core} from 'mylib';

var set = new Set();
set.add();
set.remove();
// set.product() is not available


// app/index2.js

import {core} from 'mylib';
import {relational} from 'mylib';

var set = new Set();
set.add();
set.remove();
set.product() //is available

Bonus question

All these modules are made to be available through a common namespace, let's call it MyLibrary. The core module adds MyLibrary.Core, and the relational module adds some objects into the MyLibrary.Core, and also adds MyLibrary.Relational.

Let's say I publish another module, only used to act as a facade for the other modules. Let's call this module my-library.

If a user installs the my-library, core and relational modules with npm.

npm install my-library && npm install core and nom-install relational

In the client application I would like the user of the library to only have to write

var lib = require('my-library');

Then, my-library would automatically check all installed MyLibrary modules, require them and populate the MyLibrary namespace and return it.

How an I tell the my-library module, the first time it is accessed, in both node and browser env to

  1. Check for any available MyLibrary module (browser and node environments)
  2. Run a method for each module (to install them in the namespace)
  3. Return that nice fruity namespace
Community
  • 1
  • 1
Ludovic C
  • 2,855
  • 20
  • 40

1 Answers1

2

If you're just writing declaration files, you can use interfaces instead and do something like what moment-timezone does.

moment.d.ts

declare module moment {
    interface Moment {
        // ...
    }

    interface MomentStatic {
        // ...
    }
}
declare module 'moment' {
    var _tmp: moment.MomentStatic;
    export = _tmp;
}

moment-timezone.d.ts

Just redeclare the same interfaces with extra functions.

declare module moment {
    interface Moment {
        tz(): void;
    }

    interface MomentStatic {
        tz(): void;
    }
}
declare module 'moment-timezone' {
    var _tmp: moment.MomentStatic;
    export = _tmp;
}

Both packages are identical now, and moment gets the new methods automatically.

Louay Alakkad
  • 7,132
  • 2
  • 22
  • 45
  • Hi there. The problem is I'm writing the whole thing in typescript , not just declaration files... – Ludovic C Dec 26 '15 at 17:39
  • In that case I believe you'll have to write declaration files manually or use a tool to generate them. In both cases you can only rely on interfaces. No other option that I know of unfortunately. – Louay Alakkad Dec 26 '15 at 17:41