Question

Is there a way to define a property in a TypeScript module?

None of these compile:

module My {
    // doesnt work
    get Value(): number { return 42; }

    // doesn't work either
    get function Value(): number { return 42; }

    // nope
    function get Value(): number { return 42; }
}

Right now I'm forced to use this:

module My {
    declare var Value: number;
    Object.defineProperty(My, "Value", {
        get: () => 42
    });
}

The second form seems messy to me and the code hinting doesn't really treat it as a read-only property but as a plain variable.

Is there any standard way of defining properties directly inside modules?

Was it helpful?

Solution

No, there's not a way to declare a property on a module in TypeScript using any documented language features.

You can do it in several slightly round-about techniques.

A module can extend an existing class or function. So, I've created a class with a static property, and then later created a module that uses the same name as the class.

class My
{
    static get Value():Number {
        return 42;
    }
}

module My {
    var works: boolean = true;
}

alert(My.Value);

It does generate one oddity in the JavaScript generated code that you wouldn't do manually (and should be removed by most optimizers anyway) ... it will redeclare the variable My when the module is created. This does not cause a run-time issue as the variable was already lifted in JavaScript and will not conflict with the first usage.

Here's another option:

module Global {
    class Inner {
        get Value():Number {
            return 42;
        }       
    }   
    export var My;
    My = new Inner();
}

var My = Global.My;
alert(My.Value);

While it presents an extra namespace, you can manipulate it however you'd like and use the inner class or change it as needed. This way, the My variable is global, just like it would be as a module.

OTHER TIPS

Instead of using the module keyword, consider instead using export, which will allow you to do what you want to do, treating the file itself as a module (which is how CommonJS and AMD both work).

// in My.ts
var My = {
  get value() {
    return 42;
  }
};

export = My;


// in foo.ts
import My = require('My');
console.log(My.value);

I describe this in greater detail in a blog post, The Definitive Guide to TypeScript.

I tried the singleton

let My = {
  get value() {
    return 42;
  }
}

export My

but ran into an issue where the emitted JS still said get value() and didn't work on older versions of Node. I tried Object.defineProperty but then lost TypeScript compatibility. Here's my bridge that fixes both cases:

interface My {
  value: number
}

// type assertion fixes TypeScript usage
let my = <My>{}
// defineProperty fixes JS usage
Object.defineProperty(my, 'value', {
  get: () => 42
});

export = my;

It's used like a module in typescript

import * as my from './my'

my.property // returns 42
// my.property = doesn't work
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top