Given the following TypeScript file,
export = {};
tsc
(with "module": "amd"
) will emit:
define(["require", "exports"], function (require, exports) {
"use strict";
return {};
});
However, I would rather it emit
define([], function() {
"use strict";
return {};
});
... and only include require
or exports
if I explicitly import them, i.e.
import relativeRequire = require("require");
Is there any way to tell TypeScript not to emit require
and exports
in emitted AMD modules (i.e. ask it not to use the CommonJS simplified wrapping)?
Notes:
require
, exports
, and module
dependencies).UPDATE 4 July 2017: Looks like this is actually an open issue in the TypeScript GitHub repo: https://github.com/Microsoft/TypeScript/issues/669
Any ideas for a pragmatic workaround until this gets implemented? (Or, is there actually some way to make TypeScript do this?)
I see no substantial advantage in what you are trying to do. Whatever execution time is saved by removing the unused dependencies will be dwarfed by the execution time of the rest of the app, for any app that is more than a toy app. Both require
and exports
are virtual modules that cost very little to instantiate. (By "virtual" I mean they are completely internal to the AMD loader you use and do not entail any fetching from the network or a file on disk.) I see issue 669 you mention has been open since September 2014 and deemed "accepted" since April 2015. No one seems to be hurting so badly that they are rushing to produce a pull request.
I don't know of any way TypeScript will do what you want out of the box. I recently researched how TypeScript emits its define
calls because I needed to add the virtual module named "module"
to the list of dependencies. (If you use Angular, you want to use module.id
to pass the id of the current module to Angular so that it can resolve things like relative template paths, etc. You can use module.id
without issue with CommonJS output but with AMD output module
is not included by default in the list of dependencies.) I worked around the issue by writing a build step that modifies the code that tsc
emits, after tsc
has emitted it. It uses a regexp that modifies the dependency list to add "module"
, and modifies the callback to add the corresponding argument. This works for me because I'm adding. It is not a good enough approach for what you are trying to do because you want to remove dependencies but there may be cases where removing them would result in invalid code.
For a workaround, you could use Esprima to examine the JavaScript generated by tsc
and if the values of the modules "require"
and "exports"
are not used by the code inside the factory function passed to define
, then remove the unused modules from the dependency list and the corresponding arguments from the argument list passed to the factory function. This would be the most general solution. (Among other things, it would be compatible with using the asynchronous require
call that AMD loaders make available (of the form require([...], function (...) {})
) inside the factory function.) But coding this logic may be just as involved as it would be to produce a pull request have tsc
emit the code you want in the first place.
You said:
.. and only include require or exports if I explicitly import them, i.e.
import relativeRequire = require("require");
You can't use require
unless its already there. So its good that its there.
exports
is needed as soon as you export something. If you want to have a root export as in export =
then TypeScript maps it to return
. But with export const foo = 123
it would need to use exports
.
There is no harm in it being there and any performance impact is truly minimal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With