一.構文フォーマット
TypeScript は ES Module 規範と互換性があり、ファイルがモジュールです
簡単に言えば、ファイル中に合法な import または export 文が含まれている場合、モジュールとして扱われます(モジュールスコープを持ち)、否则グローバルスコープ下で実行されます。例えば:
let x = 1
function f() { }
// 会被编译成
var x = 1;
function f() { }
// 而
let x = 1
export function f() { }
// 会被编译成(以 AMD 形式为例)
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var x = 1;
function f() { }
exports.f = f;
});
あらゆる宣言は import/export 可能で、インターフェース、タイプエイリアスなどを含みます:
export interface StringValidator {
isAcceptable(s: string): boolean;
}
export type PhoneNumber = string;
特殊的、純粋な宣言ファイル(例えば d.ts)は実際的な意味のあるコードを生成しませんが、それでもモジュール(スコープ)隔離を持ちます:
// 上例会被编译成
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
});
これも d.ts 分類 の根拠の 1 つです
P.S. import/export 具体構文は ES Module を参照。ここでは展開しません
CommonJS モジュールサポート
[CommonJS と AMD モジュール](/articles/module-es6 笔记 13/#articleHeader2) をサポートするために、TypeScript は特殊な構文を提供します:
export = something;
モジュールのエクスポートオブジェクトを定義するために使用され、NodeJS 内の以下に類似:
// NodeJS モジュール(CommonJS)
let x = {a: 1};
exports.x = x;
module.exports = x;
TypeScript に書き換えるとこのようになります:
let x = {a: 1};
export = x;
// 会被编译成
define(["require", "exports"], function (require, exports) {
"use strict";
var x = { a: 1 };
return x;
});
対応するインポート構文も NodeJS(require('./myModule.js'))とは異なります:
import module = require("myModule")
二.モジュールコード生成
コンパイルオプション(--module または -m)を通じて生成コードのモジュールフォーマットを指定できます:
// tsc -m xxx
'commonjs' # NodeJS モジュール定義
'amd' # AMD
'system' # SystemJS
'umd' # UMD
'es6' # ES Module
'es2015' # es6 と等価
'esnext' # まだ ES 規範に収録されていない最先端モジュール定義、例えば `import(), import.meta` など
'none' # すべてのモジュール定義を無効化、例えば import, export など(使用するとエラー)
デフォルトモジュールフォーマットは CommonJS または ES6 で、--target オプションに関係します(target === "ES3" or "ES5" ? "CommonJS" : "ES6")。もし将来の新バージョン ES 規範中でモジュール定義に変更がある場合、さらに es2019, es2020... などの値が追加され、ES 規範の各バージョン中のモジュール定義に対応します(モジュール定義に変更がない場合は、追加しません)
P.S. 具体のモジュール生成例は、Code Generation for Modules を参照
--module と --target
--target(または -t)オプションは --module と非常に似ており、値は以下の通り:
// tsc -t xxx
'es3'
'es5'
'es2015'
'es2016'
'es2017'
'es2018'
'esnext'
生成される目標コードがどのバージョンの規範で定義された言語特性をサポートするかを表します(デフォルト ES3)。--module オプションとは独立しています:
The module system is independent of the language implementation.
完全に ES6 モジュールフォーマットを満たす ES5 コードをコンパイル生成できるからです。例えば:
// tsconfig.json
"compilerOptions": {
"target": "es5",
"module": "es6"
}
さらに、値も --module とは異なり、各バージョンの ES 規範は 1 つの --target 具体値に対応します。各バージョンごとに新しい特性が追加されるためです
P.S. より多くの関連討論は、Understanding "target" and "module" in tsconfig を参照
P.S. 注意、--module と --target はすべて生成される目標コードを対象としたもので、ソースコードとは無関係 です(ソースコードは完全に ES 特性全開でも構いません。例えば --lib で ES2016, es2017... を指定)
三.モジュールインポート
一般に、import/require は目標モジュールソースコードをインポートし、そこからタイプ情報を抽出します。例えば:
// myModule.ts
export default {
name: 'my-module',
f() {
console.log('this is my module.');
}
}
// index.ts
import MyModule from './MyModule';
let m = MyModule;
// m のタイプ为 { name: string; f(): void; }
m.f();
(--module commonjs 下で)index.ts のコンパイル結果は:
exports.__esModule = true;
var MyModule_1 = require("./MyModule");
var m = MyModule_1["default"];
// m のタイプ为 { name: string; f(): void; }
m.f();
オンデマンドロード
特殊的、生成される目標コード中でインポートされたモジュールが使用されていない場合(例えばタイプ注釈中でのみ使用)、コンパイル時にモジュール参照が自動的に削除されます:
// index.ts
import MyModule from './MyModule';
let m: typeof MyModule;
// 编译结果
exports.__esModule = true;
var m;
この非必須参照を除去(reference-elision) する特性は、オンデマンドロードのシナリオで特に重要です:
// タイプをインポート
import MyModule from './MyModule';
declare function require(moduleName: string): any;
let someCondition: boolean;
if (someCondition) {
let m: typeof MyModule = require('./MyModule');
// 同様に正しいタイプを持ちます
m.f();
}
// 编译结果
"use strict";
exports.__esModule = true;
var someCondition;
if (someCondition) {
var m = require('./MyModule');
// 同様に正しいタイプを持ちます
m.f();
}
四.モジュールタイプ宣言
タイプが不足しているサードパーティモジュールに対して、宣言ファイル(d.ts) を通じてタイプ宣言を補充できます
具体的には、declare module 'my-module' {} 構文はモジュールを宣言できます(import/require 可能):
// types.d.ts
declare module "my-module" {
function f(): string;
}
// index.ts
import { f } from "my-module";
const result: string = f();
この方式を通じてサードパーティモジュールのタイプを補填できますが、もし素早く使用したいだけ(手動でタイプを補いたくない)の場合、メンバー宣言を省略できます。そのすべてのメンバーは any タイプになります:
// types.d.ts
declare module "my-module";
// index.ts
import x, {y} from "my-module";
x(y);
ワイルドカード
特殊的、一部のローディングシステムは非 JavaScript コンテンツのインポートをサポートします。例えば AMD:
define(['text!../templates/start.html'], function (template) {
//do something with the template text string.
});
此時モジュールワイルドカードを通じてそのタイプを定義できます:
// text! で始まるすべてのモジュールのタイプを記述
declare module "text!*" {
const content: string;
export default content;
}
// !text で終わるすべてのモジュールのタイプを記述
declare module "*!text" {
const content: string;
export default content;
}
これらの特殊なモジュールはタイプ情報を持ちます:
import html from 'text!../templates/start.html';
// 正确
html.trim();
UMD モジュール
UMD の特徴は CommonJS と AMD モジュールローディングと互換性があり、グローバルに露出して直接使用もできるため、そのモジュール宣言も比較的特殊です:
// math-lib.d.ts
export function isPrime(x: number): boolean;
export as namespace mathLib;
2 種類の参照方式:
// 直接グローバル変数を通じてアクセス
mathLib.isPrime(12);
// モジュールインポート
import { isPrime } from './math-lib';
isPrime(122);
コメントはまだありません