Here is SystemJS + TypeScript plunk, created from official Angular plunk template.
It throws
(SystemJS) SyntaxError: Missing initializer in const declaration
at eval ()
...
error and obviously evaluates .ts file as ordinary JavaScript when the file doesn't contain import
or export
statements:
main.ts
const foo: boolean = 'foo';
console.log(foo);
config.js
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
...
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
...
}
});
index.html
...
<script src="https://unpkg.com/[email protected]/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
...
But the same plunk is fine when the file has signs of ES6 module:
main.ts
const foo: boolean = 'foo';
console.log(foo);
export default null;
Obviously, if a file has .ts extension, I would prefer to evaluate it as TypeScript, whether it imports something or not.
Why does this happen in this setup? How can this be fixed?
SystemJS will probably work as follows:
> System.import('app')
- where is 'app'?
> map: { 'app': './src', ...
- Okay, 'app' is './src'
- './src' ??
> packages: { app: { main: './main.ts',
- Aha, './src/main.ts'
> ./src/main.ts
- Which format??
- 'system' ? -> No
- 'esm' ? -> No (if YES, use transpiler: 'typescript')
- 'amd' ? -> No
- 'cjs' ? -> No
- 'global' ? -> Yes -> No transpiler needed.
> evaluate ./src/main.ts
- What is ':string' in JavaScript?
- Exception!!!
Module format detection
When the module format is not set, automatic regular-expression-based detection is used. This module format detection is never completely accurate, but caters well for the majority use cases.
If auto-detection fails, you must specify it manually.
Method 1: Add hints to source
ex1: add export
(from question)
const foo: boolean = 'foo';
console.log(foo);
export default null;
ex2: add export
export const foo: boolean = 'foo';
console.log(foo);
Method 2: Add format
configuration
ex1: packages / path / meta / pattern(./main.ts or ./*.ts) / format
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts',
meta: {
'./main.ts': {
format: 'esm'
}
}
}
ex2: packages / path / format
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts',
format: 'esm'
}
}
ex3: meta / pattern (need app/ prefix) / format
(outside packages)
meta: {
'app/main.ts': {
format: 'esm'
}
}
Disclaimer: This comes from just a little debugging, I'm not actually experienced in the subject so any corrections to my understanding are welcome.
SystemJS will only perform transpilation if the module format is determined properly. If the module format is not informed, it uses a fast heuristic to try and determine it (basically, a regular expression over the source). This heuristic works when you have the import statement and fails when you don't. The actual fix for your set up is to add the module format explicitly to the package like so:
app: {
main: './main.ts',
defaultExtension: 'ts',
format:'esm' // << Module format.
},
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