9

I am using AMD modules (compiler flag "--module amd") in my TypeScript project. While I can easily use getters/setters on my classes I would like to do the same on my modules but

export get abc() : string {
    return "abc";
}

returns

error TS1008: Unexpected token; 'module, class, interface, enum, import or statement' expected.

and

export function get abc() : string {
    return "abc";
}

returns

error TS1005: '(' expected.

What am I doing wrong?

Community
  • 1
  • 1
daniel.sedlacek
  • 8,129
  • 9
  • 46
  • 77
  • 1
    possible duplicate of [Properties in a module](http://stackoverflow.com/questions/20925921/properties-in-a-module) – Acidic Mar 03 '15 at 18:38

4 Answers4

7

You can only add getters and setters to a class at the moment.

The code transformation TypeScript uses on getters and setters adds the property to the prototype of the object, which makes more sense for classes than for modules.

Fenton
  • 241,084
  • 71
  • 387
  • 401
  • 1
    aren't modules inherently Objects too? I thought getter/setter will be available on any object. – daniel.sedlacek Mar 03 '15 at 15:46
  • @daniel.sedlacek not when the object has an undefined prototype – David Sherret Mar 03 '15 at 15:57
  • @daniel.sedlacek Class getter/setters are available on the instance of the class, not the class object (i.e. the function) itself. You can probably use static getters/setters on a class and then merge the definition with a module. The type of the module will be function though. – billc.cn Mar 03 '15 at 15:59
  • 1
    @daniel.sedlacek from the `JavaScript` perspective modules are just objects. From the `TypeScript` perspective modules resemble `namespace` in `C#` or `unit` in `Delphi` - things that represent structure, not behavior – xmojmr Mar 03 '15 at 16:04
6

This is possible, using the special export = ... syntax as follows:

class MyModule {
    get abc() {
        return "abc";
    }
}

var myModule = new MyModule();
export = myModule;

This makes an instance of the class MyModule act as the API of the module. You don't have to put any data in the class - just move your functions into it and otherwise leave them unchanged. The downside is that if function a calls function b it will have to say this.b() or myModule.b() (the latter is closer to a normal module export).

Also you have to declare a named variable first. You can't just say:

export = new MyModule(); // This doesn't work
Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
0

Just for reference of future visitors ...

Similar to what @Daniel Earwicker was saying and explaining what @billc.cn was saying, you can also conflate a class with a namespace and then just define the getter/setter as a static method:

export class X {
   static get abc():string {
      return "abc";
   }
}

export namespace X {
  // ... other code
}

But this means that you will have a namespace within your library (module) and unless you want to change the way that you address attributes of your library, you will have to do the hack export = X; that @Daniel Earwicker mentioned.

https://www.typescriptlang.org/docs/handbook/declaration-merging.html

Todd
  • 877
  • 8
  • 5
-1

You can export your getter directly, via a class, like this:

// helper class to be removed when/if module-level getters are available
class _someHelper {
    static get myStaticString(): string {
        return "hi, world";
    }
}

export const myStaticString = _someHelper.myStaticString;

Then import like:

import { myStaticString } from "my-module";

Not the prettiest, but it does work.

Josh M.
  • 26,437
  • 24
  • 119
  • 200
  • 4
    I'm pretty certain this doesn't do what you think it does and can lead to unexpected errors. It may work for static getters like this (which I would argue could just be a property), but as soon as you dynamically fetch any data, it's fetched at the moment of exporting (during module resolution), so your getter effectively happens once on module resolution, and then always returns that initial value, and not the dynamic values as expected. Effectively - this means your export is no longer a getter. – iceblueorbitz Aug 05 '20 at 16:07
  • Sure, nobody should actually do this. I was answering the question as-asked though. The proper solution is to just export a function that returns the value rather than use a getter. – Josh M. Aug 06 '20 at 16:45