Skip to content

Transpiling TypeScript with other module formats #138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
guybedford opened this issue Jun 10, 2016 · 11 comments
Closed

Transpiling TypeScript with other module formats #138

guybedford opened this issue Jun 10, 2016 · 11 comments

Comments

@guybedford
Copy link
Contributor

The Babel plugin supports transpiling CommonJS when load.metadata.format == 'cjs' for a given module metadata.

In this case it will skip the registry output, effectively like a modules: none.

I tried this with the TypeScript plugin but got the error:

TypeScript transpiling to None, consider setting module: "system" in typescriptOptions to transpile directly to System.register format
logger.js:17 TypeScript Option 'isolatedModules' can only be used when either option '--module' is provided or option 'target' is 'ES2015' or higher. (TS5047)Logger.error @ logger.js:17
undefined:1 Uncaught (in promise) Error: (SystemJS) Error: TypeScript transpilation failed(…)

//cc @OliverJAsh

@patrickmichalina
Copy link

I get a similar error "TypeScript transpiling to CommonJS, consider setting module: "system" in typescriptOptions to transpile directly to System.register format" when configured to support Angular 2 component syntax with relative files

import {Component} from 'angular2/core';

@Component({
  moduleId: module.id,  <--- In order for this to work it needs to be set to 'commonjs'
  selector: 'thing-thing',
  templateUrl: 'thing.html',
  styleUrls: ['./thing.css']
})

export class ThingComponent {
   title: string = 'Thing';
}

@guybedford
Copy link
Contributor Author

@patrickmichalina use __moduleName instead of module.id for ES module support.

@patrickmichalina
Copy link

@guybedford thanks! Learn something new everyday. 👍

@frankwallis
Copy link
Owner

@guybedford that looks like a limitation of the typescript compiler itself. Also I don't think that typescript understands amd modules, so it cannot assign types to the imports and exports of an amd module, it can only check the types within the file.

I will need to try this and report back.

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jun 28, 2016

@frankwallis
TypeScript works fine with AMD modules, that is to say you can Import and Export AMD modules written in TypeScript with "module": "AMD". The types flow across the module boundaries like they do for all the other module formats. "allowSyntheticDefaultImports": true should be manually specified when using any format other than "system" for which it is enabled by default.
There is also an /// <amd-module name="jquery" /> directive which can be used to name otherwise
anonymous AMD modules when bundling. Sorry if you already knew this.

@frankwallis
Copy link
Owner

@aluanhaddad - I know that it can output AMD but I don't think that the type-checker can interpret AMD modules, so this code will not type-check but it will work at runtime if it is just transpiled:

main.ts

import message from './message';
console.log(message);

message.ts:

define(() => {
   let message: string = 'a_message';
   return message;
})

Is that incorrect? The original issue is jspm/jspm#1898

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jun 29, 2016

@frankwallis No you are correct. But that is because define is not a part of TypeScript any more than require is. The approach for doing this is to use ES module syntax and transpile the code. This generates AMD compliant JavaScript modules.
So basically,
main.ts as is and message.ts as

let message: string = 'a_message';
export default message;

This produces
message.js as

define(["require", "exports"], function (require, exports) {
    "use strict";
    var message = 'a_message';
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.default = message;
});

To expand on this a little, TypeScript does not recognize modules written by hand. It sees

define(() => {
   let message: string = 'a_message';
   return message;
})

as a script, not a module. There is some special support for commonjs modules built into the language export = and import m = require('m') (note the import is what makes this special, marking it as a module and providing type checking).

Edit: What I mean is, that TypeScript doesn't support AMD any more or less than it supports register(system) modules, but it understands their semantics and translates into them as you say.

@guybedford
Copy link
Contributor Author

@frankwallis specifically I was just intending for it to ignore the input module format for these other cases (effectively just treating them as single scripts), but at least pass the format information through to SystemJS itself so that it doesn't try and read it as register output.

@aluanhaddad
Copy link
Contributor

@guybedford I think what may be needed here is something like #96

@frankwallis
Copy link
Owner

I have introduced a configuration setting autDetectModule which I think will make it possible to compile typescript files which are a mixture of amd and es6 modules. I am not really able to test it though.

@aluanhaddad
Copy link
Contributor

That's awesome I look forward to trying it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants