4

I just started taking a look at Typescript and have an issue when playing around.
I want to write a library to manage a general tree structure and just doing some very basic tests to see how TS works.

Start of the simple setup with 3 files:

  • GForest.ts
  • GTree.ts
  • GNode.ts

Currently, GForest.ts:

import * as Immutable   from "immutable"; 
import GTree            from "./GTree"; 

export default class Forest{ 
    public static createTree(){ 
        let tree = new GTree(); 
    } 
} 

GTree.ts:

export default class GTree{ 
    constructor(){ 
        console.log("Tree constructed"); 
    } 

    public static createNode(){ 

    } 
} 

I created a simple test.js file to call the library (compiled TS to ES5):

var GForest = require("./build/GForest"); 

console.log(GForest); 

When running

> node test

The output is:

I don't understand why the result is:

{ default: { [Function: Forest] createTree: [Function] } }

Why is there an object with default as key and how do I change this to achieve desired behaviour?

Because of this, I'm unable to just call:

GForest.createTree(); 

(I want to expose the creation of a tree through a static factory) Any help?

3
  • why do you use var GForest = require("./build/GForest"); inside test.js instead of import and then compiling the file to js? Commented Nov 23, 2016 at 10:35
  • @Maximus I just run test.js as a simple node script. Not sure why I would want to write import, then compile for this (?). Commented Nov 23, 2016 at 10:39
  • Never mind, please see my answer Commented Nov 23, 2016 at 10:43

2 Answers 2

2

Use the ES6 default export

I quote the article ES6 In Depth: Modules from Mozilla:

If you’d like your own ES6 module to have a default export, that’s easy to do. There’s nothing magic about a default export; it’s just like any other export, except it’s named "default".

In your test.js file, the "default" feature is inelegant because you want to consume the ES6 default export from an ES5 syntax. I suggest to use the ES6 syntax with the help of TypeScript:

// test.ts
import GForest from "./build/GForest";
console.log(GForest); // { [Function: Forest] createTree: [Function] }

This code is compiled to:

var GForest_1 = require("./build/GForest"); 
console.log(GForest_1.default);

Directly export a class

In TypeScript, you can directly export a member with the non-standard syntax export =.

Example:

// GForest.ts
import * as Immutable   from "immutable"; 
import GTree            from "./GTree"; 

class Forest{ 
    public static createTree(){ 
        let tree = new GTree(); 
    } 
}
export = Forest;

Then, use it with a code ES3/5:

// test.js
let GForest = require("./build/GForest");
console.log(GForest); // { [Function: Forest] createTree: [Function] }

... or, in TypeScript:

// test.ts
import GForest = require("./build/GForest");
console.log(GForest); // { [Function: Forest] createTree: [Function] }

See the documentation on export = here.

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

6 Comments

Because I happen to write the lib in TS, doesn't mean that the consumer should? Test.js is just a representation of an arbitrary consumer and I prefer not to make it an opinionated lib.
@KimGysen OK, I think I understand what you need. I edited.
That's what I need... Still unclear to me why they promote the use of default export though (typescriptlang.org/docs/handbook/modules.html). Doesn't seem to add any benefit.
@KimGysen Maybe because it is the way promoted by the standard ES6?
@Maximus My bad! I forgot to remove the first export. I edited.
|
1

Why is there an object with default as key and how do I change this to achieve desired behaviour?

That's because it is what is exported from compiled GForest.js:

"use strict";
var GTree_1 = require("./GTree");
var Forest = (function () {
    function Forest() {
    }
    Forest.createTree = function () {
        var tree = new GTree_1["default"]();
    };
    return Forest;
}());
exports.__esModule = true;
exports["default"] = Forest;

You need to use .default to refer to the constructor:

var GForest = require("./build/GForest").default; 

Typescript uses es6 module syntax which can export multiple modules. This code is then compiled into commonjs es5 module syntax. Typescript compiler uses properties on exports object to map multiple exports defined on es6 module syntax. And default is just like any other named export.

4 Comments

Yes of course, but why does it do that? Isn't export default class Forest correct syntax in TS to behave as a module; why does it have to add the default property? If I want to expose this as a library, the default just makes it look ugly...
@KimGysen, updated. What module system do your library consumers will use?
Perhaps it's me, but I find this awkward. In the article: typescriptlang.org/docs/handbook/modules.html, section Guidance for structuring modules, they say: If you’re only exporting a single class or function, use export default. Yet it comes with the cost of the defaultproperty that makes the import clunky for commonjs users. However if I don't, then it is required to use braces import {GForest} etc. I'm looking for a way to export as default, and just import without unnecessary side-effects.
@KimGysen, you're referring to the documentation of TypeScript, however you use JS es5

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.