简体   繁体   中英

.ts file isn't treated as TypeScript module

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/systemjs@0.19.31/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.
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM