Typescript(インポート/エクスポート)
はじめに
TypeScript における import と export の書き方は JavaScriptと概ね同じですが、拡張子の扱いやTypeScript 固有の挙動である型のコンテキストにおけるimport,exportなどいくつか違いがあるので、この記事に書き残します。(主に自分の備忘録として...)
javascriptにおけるimport/exportについては以前記事にしましたのでそちらも参考にして下さい!
ES6(モジュール) - 駆け足エンジニアの記録
インポート/エクスポートのための準備
モジュール化するためにはいくつか設定が必要です。(webpackを使用している場合、必要ない設定等あるかもしれません)
①htmlのscriptタグ
<script type="module" src="index.js"></script>
scriptタグには本来javascriptファイルのみ記載しているところを、上記のようにtype="module"と追記する必要があります。
②tsconfigの設定
tsconfig内"module"初期状態では"module": "commonjs",となっていると思いますが、"module": "ES2015",と変更する必要があります。
ES2015以外(ES2016など)ではエラーが生じました。
③インポート時の拡張子
この記事を作るにあたって、他の記事を読んでみたところ殆どの記事でTypeScript ではインポートの際 に読み込むファイルの拡張子を省略できる。……というより、拡張子を書くとエラーになるという内容を目にしました。おそらく拡張子を書くとエラーが生じる場合というのはwebpackやgulpを利用している場合だと思われます。
ここではバンドルツールやライブラリを使用しない前提で以下のケースを考えます。
2つのファイル(index.ts,app.ts)があり、indexをインポート用appをエクスポート用のファイルとします。また簡単にobjという変数をインポート/エクスポートする例とします。
//app.ts export const obj = { name: "max", age: 22 }; //index.ts import { obj } from "./app.js"; console.log(obj);//{name: "max", age: 22}
ここでのポイントはtsではなく拡張子jsが必要ということです。appファイルをインポートするタイミングは既にjavascriptにコンパイルされた後です。最終的にはjavascriptファイルがインポートされるということです。
なので拡張子はtsではなくjsと記載しないとエラーが発生します。
以上がtypescriptにおけるインポート/エクスポートのための準備となります。
typescriptにおけるインポート/エクスポート
型定義によるインポート/エクスポート
Typescriptによる型定義(インターフェースや型エイリアス)といったものも import と export の対象になります。
//app.ts(エクスポート) interface Person { name: string; age: number; } type AddFn = (a: number, b: number) => number; export { Person, AddFn }; //index.ts(インポート) import { Person, AddFn } from "./app.js"; const user1: Person = { name: "max", age: 22, }; console.log(user1);//{name: "max", age: 22} const addFn: AddFn = (a, b) => { return a + b; }; console.log(addFn(2, 3));//5
②コンビネーションにおけるインポート/エクスポート
先に例を提示します。以下BMIの値を求めるという例です。
//app.ts(エクスポート) type Gender = "male" | "female"; interface Person { name: string; height: number; weight: number; gender: Gender; } const Person = { BMI: (person: Person): number => { const cmFromM = person.height / 100; const stWeight = cmFromM * cmFromM; return Math.floor(person.weight / stWeight); }, }; export { Person };
インターフェースとオブジェクトが、同じ Person という名前で定義されてます。TypeScript では、同じ名前空間の中に『変数宣言空間(Variable Declaration Space)』と『型宣言空間(Type Declaration Space)』という 2 つの宣言空間が存在してい て、名前の管理が別々になっています。そのためPersonのように変数や関数と型で同一の名前を持つことができます。型と同じ名前のオブジェクトを定義することを一般にコンビネーションと呼ばれます。
export { Person}によるエクスポートはインターフェースのPersonとオブジェクトのPersonどちらもエクスポートされます。
//index.ts(インポート) import { Person } from "./app.js"; const user1: Person = { name: "hiroki", height: 179, weight: 71, gender: "male", }; console.log(Person.BMI(user1));//22
このようにインターフェースの Person とオブジェクトの Personを一つのインポート文でどちらも使えるようになります。