.ts 文件不被视为 TypeScript 模块

.ts file isn't treated as TypeScript module

Here is SystemJS + TypeScript plunk, created from official Angular plunk template.

它抛出

(SystemJS) SyntaxError: Missing initializer in const declaration

at eval ()

...

错误,当文件不包含 importexport 语句时,显然将 .ts 文件评估为普通 JavaScript:

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>
...

但是the same plunk is fine当文件有ES6模块的标志时:

main.ts

const foo: boolean = 'foo';

console.log(foo);

export default null;

显然,如果一个文件有 .ts 扩展名,我更愿意将它评估为 TypeScript,无论它是否导入某些东西。

为什么在这个设置中会发生这种情况?如何解决?

免责声明:这只是一些调试,我在这方面没有实际经验,所以欢迎对我的理解进行任何更正。

SystemJS 只会在正确确定模块格式的情况下执行转译。如果未通知模块格式,它会使用快速启发式方法来尝试确定它(基本上是源上的正则表达式)。 当您有 import 语句时,此试探法有效,而当您没有时失败。 您的设置的实际修复是将模块格式显式添加到包中,如下所示:

app: {
  main: './main.ts',
  defaultExtension: 'ts',
  format:'esm' // << Module format.
},

SystemJS 可能会按如下方式工作:

> 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.

如果自动检测失败,您必须手动指定。

方法一:给source添加提示

ex1:添加 export(来自问题)

const foo: boolean = 'foo';
console.log(foo);
export default null;

ex2: 添加 export

export const foo: boolean = 'foo';
console.log(foo);

方法二:添加format配置

ex1: packages/path/meta/pattern(./main.ts or ./*.ts) / format

packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts',
      meta: {
       './main.ts': {
           format: 'esm'
        }
      } 
    }

ex2: 包/路径/format

packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts',
      format: 'esm'
    }
}

ex3: meta / pattern (需要 app/ 前缀) / format (外包)

meta: {
    'app/main.ts': {
        format: 'esm'
    }
}