diff --git a/docs/documentation/ja/tutorials/Babel with TypeScript.md b/docs/documentation/ja/tutorials/Babel with TypeScript.md new file mode 100644 index 00000000..cdda48b5 --- /dev/null +++ b/docs/documentation/ja/tutorials/Babel with TypeScript.md @@ -0,0 +1,49 @@ +--- +title: TypeScriptでBabelを使用する +layout: docs +permalink: /ja/docs/handbook/babel-with-typescript.html +oneline: BabelとTypeScriptを組み合わせたプロジェクトの作成方法 +translatable: true +--- + +## BabelとTypeScriptの`tsc`の比較 + +モダンなJavaScriptプロジェクトを作る際、TypeScriptからJavaScriptにファイルをトランスパイルするにはどのような方法が正しいのでしょうか? + +その答えは、プロジェクトによって _"状況次第"_ だったり、 _"誰かが決めてくれたもの"_ であることが多いです。[tsdx](https://tsdx.io)、[Angular](https://angular.io/)、[NestJS](https://nestjs.com/)といった既存のフレームワークや、あるいは[Getting Started](/docs/home)で紹介したようなフレームワークを使ってプロジェクトを構築しているのならば、あなたに代わってこの決定を行ってくれます。 + +一方で、有用な経験則としては次のようなものがあります: + +- ビルド出力はソースの入力ファイルとほとんど同じですか?では、`tsc`を使いましょう +- 出力が複数になる可能性があるビルドパイプラインが必要ですか?では、トランスパイルには`babel`を、型チェックには`tsc`を使いましょう + +## トランスパイルのためのBabel、型のための`tsc` + +ここで紹介するのは、JavaScriptのコードベースからTypeScriptに移植された可能性がある既存のビルドインフラストラクチャを持つプロジェクトでよく見られるパターンです。 + +このテクニックは、Babelの[preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript)を使ってJSファイルを生成し、次にTypeScriptを用いて型チェックと`.d.ts`ファイルの生成を行うというハイブリッドなアプローチです。 + +BabelのTypeScriptサポートを活用することで、既存のビルドパイプラインとの連携が可能になり、また、Babelはコードの型チェックを行わないため、JS出力にかかる時間が短縮できる可能性が高まります。 + +#### 型チェックとd.tsファイルの生成 + +Babelを使う際の欠点としては、TSからJSへのトランスパイルを行う際に型チェックを受けられないことがあります。これは、エディタで見逃した型エラーが本番コードに潜り込んでしまうかもしれないことを意味します。 + +加えて、BabelはTypeScript用の`.d.ts`ファイルを生成することができないため、プロジェクトがライブラリである場合、そのライブラリを扱うのが難しくなる可能性があります。 + +こうした問題を解決するには、TSCを使ってプロジェクトの型チェックを行うコマンドを設定する必要があります。これはおそらく、Babelの設定の一部を対応する[`tsconfig.json`](/tsconfig)にコピーし、次のフラグが有効になっていることを確認することになるでしょう: + +```json tsconfig +"compilerOptions": { + // tscによって.d.tsファイルを作成させますが、.jsファイルは作成されないようにします + "declaration": true, + "emitDeclarationOnly": true, + // BabelがTypeScriptプロジェクト内のファイルを安全にトランスパイルできるようにします + "isolatedModules": true +} +``` + +上記のフラグの詳細についてはこちらをご確認ください: + +- [`isolatedModules`](/tsconfig#isolatedModules) +- [`declaration`](/tsconfig#declaration)、[`emitDeclarationOnly`](/tsconfig#emitDeclarationOnly) diff --git a/docs/documentation/ja/tutorials/DOM Manipulation.md b/docs/documentation/ja/tutorials/DOM Manipulation.md new file mode 100755 index 00000000..13d8fd89 --- /dev/null +++ b/docs/documentation/ja/tutorials/DOM Manipulation.md @@ -0,0 +1,201 @@ +--- +title: DOMの操作 +layout: docs +permalink: /ja/docs/handbook/dom-manipulation.html +oneline: TypeScriptでDOMを扱う +translatable: true +--- + +## DOMの操作 + +### _`HTMLElement`型の探索_ + +標準化されてから20年以上の間に、JavaScriptは非常に長い道のりを歩んできました。2020年には、JavaScriptはサーバー上、データサイエンス、さらにはIoTデバイスでさえも使用できるようになりましたが、最も一般的なユースケースであるWebブラウザについて覚えておくことが重要です。 + +Webサイトは、HTMLおよびXMLドキュメントで構成されています。これらのドキュメントは静的で、変化しません。_Document Object Model (DOM)_ は、静的なWebサイトを機能的にするためにブラウザによって実装されたプログラミングインターフェースです。DOM APIは、ドキュメントの構造、スタイル、そして内容を変更するために使うことができます。このAPIはとても強力なので、動的なWebサイトを簡単に作成するために数え切れないほど多くのフロントエンドフレームワーク(jQuery、React、Angularなど)が開発されてきました。 + +TypeScriptはJavaScriptの型付きスーパーセットであり、DOM APIの型定義を提供しています。こうした定義はあらゆるデフォルトのTypeScriptプロジェクトでもすぐに利用できるようになっています。20,000行を超える _lib.dom.d.ts_ の定義の中で、ひときわ目立つものがあります。それが`HTMLElement`です。この型はTypeScriptでのDOM操作の根幹となるものです。 + +> [DOMの型定義](https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts)のソースコードを細かく調べることができます + +## 基本的な例 + +次のような単純化された _index.html_ ファイルがあるとします: + + + + TypeScript Dom Manipulation + +
+ + + + + +`#app`要素に`

Hello, World

`要素を追加するTypeScriptのスクリプトを見てみましょう。 + +```ts +// 1. idプロパティを使ってdiv要素を選択します +const app = document.getElementById("app"); + +// 2. プログラムによって新しい

要素を作成します +const p = document.createElement("p"); + +// 3. テキストの内容を追加します +p.textContent = "Hello, World!"; + +// 4. p要素をdiv要素に追加します +app?.appendChild(p); +``` + +コンパイルして、 _index.html_ ページを開くと、HTMLは結果的に次のようになります: + +```html +
+

Hello, World!

+
+``` + +## `Document`インターフェース + +TypeScriptの最初の行では、グローバル変数`document`を使用しています。この変数を調べてみると、_lib.dom.d.ts_ ファイルの`Document`インターフェースで定義されていることが分かります。コードスニペットには、`getElementById`と`createElement`の2つのメソッドの呼び出しが含まれています。 + +### `Document.getElementById` + +このメソッドの定義は次のとおりです: + +```ts +getElementById(elementId: string): HTMLElement | null; +``` + +要素のid文字列を渡し、`HTMLElement`あるいは`null`を返します。このメソッドによって、最も重要な型のひとつである`HTMLElement`が導かれます。この型は他のすべての要素のインターフェースのベースとなるインターフェースとして機能します。例えば、前述のコード例の変数`p`は、`HTMLParagraphElement`型です。また、このメソッドは`null`を返す可能性があることにも注意してください。これは、指定された要素を実際に見つけることができるかどうか、このメソッドの実行前には保証できないためです。コードスニペットの最後の行では、`appendChild`を呼び出すために、新機能の _オプショナルチェイニング_ 演算子を用いています。 + +### `Document.createElement` + +このメソッドの定義は次のとおりです (_非推奨の_ 定義は省略しています): + +```ts +createElement(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; +createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; +``` + +この関数の定義はオーバーロードされています。2番目のオーバーロードは最も単純で、`getElementById`と非常に似た動作を行います。任意の`string`を渡すと、標準のHTMLElementを返します。この定義により、開発者はユニークなHTML要素のタグを作成することができます。 + +例えば、`document.createElement('xyz')`は``要素を返しますが、これは明らかにHTMLの仕様で指定された要素ではありません。 + +> 興味ある方は、`document.getElementsByTagName`を使用してカスタムタグ要素に触れてみてください + +`createElement`の最初の定義では、複数の高度なジェネリクスパターンを使用しています。これはチャンクに分けて理解するのが最良です。まずは、ジェネリクス式``から見ていきます。この式は`HTMLElementTagNameMap`のキーに **制限された** ジェネリクスパラメータ`K`を定義しています。マップインターフェースは、指定されたすべてのHTMLタグ名とそれに対応するすべての型インターフェースを含みます。例えば、マップされた値の最初の5つは次のとおりです: + +```ts +interface HTMLElementTagNameMap { + "a": HTMLAnchorElement; + "abbr": HTMLElement; + "address": HTMLElement; + "applet": HTMLAppletElement; + "area": HTMLAreaElement; + ... +} +``` + +固有のプロパティを持たない要素は`HTMLElement`を返すだけですが、そうでない型は、(`HTMLElement`を拡張あるいは実装した)特定のインターフェースを返します。 + +さて、`createElement`定義の残りの部分、`(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]`についてですが、第一引数 `tagName`はジェネリクスパラメータ`K`として定義されています。TypeScriptのインタープリタは、賢いのでこの引数からジェネリクスパラメータを _推論_ することができます。開発者がこのメソッドを使うときには、実際にはジェネリクスパラメータを指定する必要がない、ということです。`tagName`引数に渡された値がなんであれ、`K`として推測され、定義の残りの部分を通してずっと使用することができます。その結果次のようなことが起こります。戻り値`HTMLElementTagNameMap[K]`は`tagName`引数を取り、それを使って対応する型を返します。この定義によって、前述のコードスニペットの`p`変数は`HTMLParagraphElement`型を取得します。また、もしコードが`document.createElement('a')`であったならば、`HTMLAnchorElement`型の要素を返します。 + +## `Node`インターフェース + +`document.getElementById`関数は`HTMLElement`を返します。`HTMLElement`は、`Node`インターフェースを拡張した`Element`インターフェースを拡張したものです。このプロトタイプの拡張により、すべての`HTMLElements`が標準メソッドのサブセットを活用できます。前述のコードスニペットでは、`Node`インターフェースで定義されたプロパティを使って新しい`p`要素をWebサイトに追加しています。 + +### `Node.appendChild` + +コードスニペットの最後の行は`app?.appendChild(p)`です。前述の`document.getElementById`のセクションでは、実行時に`app`がnullになる可能性があるため、ここでは _オプショナルチェイニング_ 演算子を用いることを説明しました。`appendChild`は次のように定義されています: + +```ts +appendChild(newChild: T): T; +``` + +このメソッドは`createElement`メソッドと同様に動作し、ジェネリクスパラメータ`T`は `newChild`引数から推測されます。`T`は別の基底インターフェースである`Node`に _制限_ されています。 + +## `children`と`childNodes`の違い + +前のセクションでは、`HTMLElement`インターフェースは、`Node`を拡張した`Element`を拡張したものであることについて説明しました。DOM APIには、_子_ 要素というものがあり、例えば、次のHTMLでは、`p`タグは`div`要素の子です。 + +```tsx +
+

Hello, World

+

TypeScript!

+
; + +const div = document.getElementsByTagName("div")[0]; + +div.children; +// HTMLCollection(2) [p, p] + +div.childNodes; +// NodeList(2) [p, p] +``` + +`div`要素を取得した後、`children`プロパティは、`HTMLParagraphElements`を含むリストである`HTMLCollection`を返します。`childNodes`プロパティは、同様のノードのリストである`NodeList`を返します。それぞれの`p`タグは`HTMLParagraphElements`型のままですが、`NodeList`は`HTMLCollection`リストにはない _HTMLノード_ を含めることができます。 + +テキストは保ったまま、一方の`p`タグを削除してHTMLを変更してみましょう。 + +```tsx +
+

Hello, World

+ TypeScript! +
; + +const div = document.getElementsByTagName("div")[0]; + +div.children; +// HTMLCollection(1) [p] + +div.childNodes; +// NodeList(2) [p, text] +``` + +両方のリストがどのように変化するか見てみましょう。`children`には、`

Hello, World

`要素だけが含まれるようになり、`childNodes`には、2つの`p`ノードの代わりに、`text`ノードが含まれるようになりました。`NodeList`の`text`の部分は、テキストである `TypeScript!`を含むリテラル`Node`です。この`Node`は`HTMLElement`とはみなされないため、`children`リストには含まれていません。 + +## `querySelector`と`querySelectorAll`メソッド + +これらのメソッドは、どちらもよりユニークな制約に適合するDOM要素のリストを取得するための優れたツールです。_lib.dom.d.ts_ において、次のように定義されています: + +```ts +/** + * セレクタにマッチするノードの子孫である最初の要素を返します。 + */ +querySelector(selectors: K): HTMLElementTagNameMap[K] | null; +querySelector(selectors: K): SVGElementTagNameMap[K] | null; +querySelector(selectors: string): E | null; + +/** + * セレクタにマッチするノードの子孫であるすべての要素を返します。 + */ +querySelectorAll(selectors: K): NodeListOf; +querySelectorAll(selectors: K): NodeListOf; +querySelectorAll(selectors: string): NodeListOf; +``` + +`querySelectorAll`の定義は、新しい型`NodeListOf`を返すという点以外は `getElementsByTagName`と似ています。この戻り値の型は、基本的には標準的なJavaScriptのリスト要素のカスタム実装です。まず間違いなく、`NodeListOf`を`E[]`と置き換えても、非常によく似たユーザー体験が得られるでしょう。`NodeListOf`は、`length` 、`item(index)`、`forEach((value, key, parent) => void)`、数値インデックスといったプロパティとメソッドのみを実装しています。加えて、このメソッドは`NodeList`が`.childNodes`メソッドから返していた _ノード_ ではなく、_要素_ のリストを返します。これは矛盾しているようにみえるかもしれませんが、`Element`インターフェースが`Node`を拡張したものであることを思い出してください。 + +上記のメソッドの実際の動作を確認するために、既存のコードを次のように変更しましょう: + +```tsx +
    +
  • First :)
  • +
  • Second!
  • +
  • Third times a charm.
  • +
; + +const first = document.querySelector("li"); // 最初のli要素を返す +const all = document.querySelectorAll("li"); // すべてのli要素のリストを返す +``` + +## もっと知りたいですか? + +_lib.dom.d.ts_ の型定義の最も良いところは、Mozilla Developer Network (MDN)のドキュメントサイトで注釈されている型を反映しているところです。例えば、`HTMLElement`は[HTMLElementページ](https://developer.mozilla.org/docs/Web/API/HTMLElement)に記載されています。こうしたページには、利用可能なすべてのプロパティ、メソッド、時には例さえもリストしています。こうしたページの、もう1つ素晴らしいところは、対応する標準ドキュメントのリンクを掲載している点です。上記のページには[HTMLElementのW3C勧告](https://www.w3.org/TR/html52/dom.html#htmlelement)のリンクがあります。 + +資料: + +- [ECMA-262 Standard](http://www.ecma-international.org/ecma-262/10.0/index.html) +- [DOMの紹介](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) diff --git a/docs/documentation/ja/tutorials/Migrating from JavaScript.md b/docs/documentation/ja/tutorials/Migrating from JavaScript.md new file mode 100644 index 00000000..7ebba6ad --- /dev/null +++ b/docs/documentation/ja/tutorials/Migrating from JavaScript.md @@ -0,0 +1,442 @@ +--- +title: JavaScriptからの移行 +layout: docs +permalink: /ja/docs/handbook/migrating-from-javascript.html +oneline: JavaScriptからTypeScriptに移行する方法 +--- + +TypeScriptはそれ単独で存在しているわけではありません。 +JavaScriptのエコシステムを念頭において構築されたものであり、今日ではたくさんのJavaScriptが存在しています。 +JavaScriptのコードベースをTypeScriptに移行することは、多少面倒ですが、通常は難しくはありません。 +本チュートリアルでは、どのようにして移行を開始するのが良いのかについて見ていきましょう。 +新しいTypeScriptコードを記述するためのハンドブックを十分読み込んだことを前提としています。 + +Reactプロジェクトでの移行を考えているのであれば、まずは[React Conversion Guide](https://github.com/Microsoft/TypeScript-React-Conversion-Guide#typescript-react-conversion-guide)を読むことをおすすめします。 + +## ディレクトリの設定 + +素のJavaScriptを書いているならば、JavaScriptを直接実行している可能性が高いです。 +この場合、`.js`ファイルは`src`、`lib`、あるいは`dist`ディレクトリに置かれ、必要に応じて実行されていることでしょう。 + +こうしたケースでは、記述したファイルはTypeScriptの入力として使用され、TypeScriptが生成する出力を実行することになります。 +JSからTSへの移行中、TypeScriptが入力ファイルを上書きしないように入力ファイルを分離する必要があります。 +出力ファイルを特定のディレクトリに置く必要がある場合、そのディレクトリが出力ディレクトリとなります。 + +バンドルしたり、Babelのような別のトランスパイラを使ったり、JavaScriptに対して中間ステップを実行していることがあるかもしれません。 +この場合は、すでに上述したようなフォルダ構成が設定されている可能性があります。 + +ここからは、ディレクトリが次のように設定されていると仮定します: + +``` +projectRoot +├── src +│ ├── file1.js +│ └── file2.js +├── built +└── tsconfig.json +``` + +`src`ディレクトリの外に`tests`フォルダがある場合、`src`の中に`tsconfig.json`をひとつ置き、`tests`の中にもひとつ置くことができます。 + +## 設定ファイルの記述 + +TypeScriptは、どのファイルを含めたいのか、どの種類のチェックを実行したいのかといったプロジェクトの設定を管理する`tsconfig.json`と呼ばれるファイルを使用します。 +プロジェクトにとって必要最低限の設定ファイルを作成してみましょう: + +```json +{ + "compilerOptions": { + "outDir": "./built", + "allowJs": true, + "target": "es5" + }, + "include": ["./src/**/*"] +} +``` + +上記では、TypeScriptに対して数点指定しています: + +1. `src`ディレクトリにある解釈可能なファイルを読み込む(`include`にて) +2. JavaScriptファイルを入力ファイルとして許可する(`allowJs`にて) +3. `built`ディレクトリにすべての出力ファイルを出力する(`outDir`にて) +4. 新しいJavaScriptの構造をECMAScript5のようなより古いバージョンに変換する(`target`にて) + +この時点でプロジェクトのルートで`tsc`を実行してみると、`built`ディレクトリに出力ファイルが確認できるはずです。 +`built`にあるファイルのレイアウトは`src`のものと同じように見えるでしょう。 +これで、あなたのプロジェクトにおいて、TypeScriptが動作するようになりました。 + +## 初期に導入することによるメリット + +この段階でも、TypeScriptがあなたのプロジェクトを理解することで受けられるメリットがいくつかあります。 +[VS Code](https://code.visualstudio.com)や[Visual Studio](https://visualstudio.com)のようなエディタを開くと、補完などのツールによるサポートをたびたび受けられることが確認できるでしょう。 +また、以下のようなオプションを設定することで、特定のバグを発見することもできます: + +- `noImplicitReturns`は、関数の最後の戻り値の設定忘れを防止します。 +- `noFallthroughCasesInSwitch`は、`switch`ブロックの`case`間で`break`文を忘れたくない時に便利です。 + +TypeScriptは、到達不可能なコードやラベルについても警告します。この警告は、それぞれ`allowUnreachableCode`と`allowUnusedLabels`でオフにできます。 + +## ビルドツールとの統合 + +パイプラインにもっと多くのビルドステップが存在しているかもしれません。 +もしかしたらそれぞれのファイルに何か他のファイルを連結していることもあるでしょう。 +それぞれビルドツールは異なりますが、ここではその要点をできる限りカバーします。 + +## Gulp + +Gulpを何らかの方法で使用してる場合は、TypeScriptと[Gulpの使用](/docs/handbook/gulp.html)について、およびBrowserify、Babelify、Uglifyといった一般的なビルドツールとの統合についてのチュートリアルがあります。 +詳しくはそちらをご確認ください。 + +## Webpack + +Webpackとの統合はとても簡単です。 +TypeScriptローダーである`ts-loader`と、デバッグを簡単にするための`source-map-loader`を組み合わせることができます。 +次のコマンドを実行します + +```shell +npm install ts-loader source-map-loader +``` + +そして、以下のオプションを`webpack.config.js`ファイルにマージします: + +```js +module.exports = { + entry: "./src/index.ts", + output: { + filename: "./dist/bundle.js", + }, + + // webpack の出力をデバッグするためのソースマップを有効にします。 + devtool: "source-map", + + resolve: { + // 解決可能な拡張子として'.ts'と'.tsx'を追加します。 + extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"], + }, + + module: { + rules: [ + // '.ts'または'.tsx'拡張子を持つすべてのファイルは'ts-loader'によって処理されます。 + { test: /\.tsx?$/, loader: "ts-loader" }, + + // 出力されるすべての'.js'ファイルは'source-map-loader'によって再処理されたソースマップを持ちます。 + { test: /\.js$/, loader: "source-map-loader" }, + ], + }, + + // その他のオプション... +}; +``` + +重要なのは、`.js`ファイルを扱う他のどのローダーよりも先に、ts-loaderを実行する必要があるという点です。 + +WebpackのもうひとつのTypeScriptローダーである[awesome-typescript-loader](https://github.com/TypeStrong/ts-loader)でも同様です。 +この2つの違いについては、[こちら](https://github.com/s-panferov/awesome-typescript-loader#differences-between-ts-loader)を参照してください。 + +Webpackを使用している例は、[ReactとWebpackのチュートリアル](/docs/handbook/react-&-webpack.html)で確認することができます。 + +## TypeScriptファイルに移行する + +ここまでで、TypeScriptファイルを使い始める準備ができたことでしょう。 +移行の最初のステップとして、`.js`ファイルを`.ts`にリネームします。 +もしファイルがJSXを使用している場合は、`.tsx`にリネームする必要があります。 + +このステップを終えましたか? +いいですね! +これでJavaScriptからTypeScriptへのファイルの移行に成功しました! + +もちろん、このステップが正しくないと思うかもしれません。 +TypeScriptサポートがあるエディタでファイルを開く(あるいは `tsc --pretty` を実行する)と、特定の行に赤い波線が表示されている可能性があります。 +これは、Microsoft Wordようなエディタの赤い波線と同じように考えてください。 +赤い波線があってもWordで文書を印刷することができるのと同じように、赤い波線があってもTypeScriptはコードを変換します。 + +これが手抜きだと思うならば、このふるまいを厳しくすることができます。 +例えば、エラーがあるときはTypeScriptにJavaScriptへのコンパイルを _させたくない_ 場合、`noEmitOnError`オプションを使うことができます。 +そうした意味では、TypeScriptには厳しさの段階があり、そのつまみを好きなだけ強くすることができると言えます。 + +もし利用可能なより厳しい設定を使用するつもりならば、今のうちに設定を有効化しておくのがベストです(後述の[より厳密なチェック](#getting-stricter-checks)を確認してください)。 +例えば、明示的に指定していない型をTypeScriptが`any`と暗黙的に推測することを望まない場合、ファイルの修正を始める前に`noImplicitAny`を使いましょう。 +修正すべきコードが多くて多少困惑するかもしれませんが、長期的な利益をかなり早い時点で受けることができます。 + +## エラーの除去 + +前述したように、変換後にエラーメッセージが出ることは予測できないことではありません。 +重要なことは、実際にエラーをひとつひとつ確認して、そのエラーにどう対処するかを決めることです。 +多くの場合、これらは妥当なバグなのですが、時には何をしようとしているのかをTypeScriptにもう少し上手に説明しなければならないこともあるでしょう。 + +### Modulesからのインポート + +最初は、`Cannot find name 'require'.`や`Cannot find name 'define'.`といったエラーがたくさん表示されるかもしれません。 +このようなケースでは、おそらくモジュールを使用していることでしょう。 +これらの呼び出しが存在していることをTypeScriptに確信させるには、次のようなコードや + +```ts +// Node/CommonJS用 +declare function require(path: string): any; +``` + +あるいは次のようなコード + +```ts +// RequireJS/AMD用 +declare function define(...args: any[]): any; +``` + +を記述することもできますが、これらの呼び出しを削除し、インポートにはTypeScriptの構文を使った方が良いでしょう。 + +まず、TypeScriptの`module`フラグを設定してモジュールシステムを有効化する必要があります。 +有効なオプションは、`commonjs`、`amd`、`system`そして`umd`です。 + +以下のようなNode/CommonJSコード: + +```js +var foo = require("foo"); + +foo.doStuff(); +``` + +あるいは次のような RequireJS/AMDコードがあったとします: + +```js +define(["foo"], function (foo) { + foo.doStuff(); +}); +``` + +その場合、次のようなTypeScriptコードを記述することになります: + +```ts +import foo = require("foo"); + +foo.doStuff(); +``` + +### 宣言ファイルの取得 + +TypeScriptのインポートに変換し始めた場合、おそらく`Cannot find module 'foo'.`といったエラーに遭遇するでしょう。 +ここでの問題は、ライブラリを記述するための _宣言ファイル_ を持っていないことです。 +幸運なことに、これはとても簡単に解決できます。 +TypeScriptが`lodash`のようなパッケージについて文句を言ってきたら、ただ次のように記述すればよいのです + +```shell +npm install -S @types/lodash +``` + +もし、`commonjs`以外のモジュールオプションを使用しているならば、`moduleResolution`オプションに`node`を設定する必要があるでしょう。 + +これで、問題なくlodashをインポートして、正確な補完を得ることができます。 + +### モジュールからのエクスポート + +通常、モジュールからのエクスポートは、`exports`や`module.exports`のような値にプロパティを追加することを必要とします。 +TypeScriptでは、トップレベルのエクスポート宣言を使うことができます。 +例えば、次のような関数をエクスポートしたとします: + +```js +module.exports.feedPets = function (pets) { + // ... +}; +``` + +これは、次のように記述することもできます: + +```ts +export function feedPets(pets) { + // ... +} +``` + +時々、exportsオブジェクトを完全に上書きすることがあります。 +これは、以下のスニペットのように、すぐに呼び出すことのできるモジュールを作成するために、よく使われるパターンです: + +```js +var express = require("express"); +var app = express(); +``` + +以前は次のように記述していたかもしれません: + +```js +function foo() { + // ... +} +module.exports = foo; +``` + +TypeScriptでは、`export =`構造体でモデル化することができます。 + +```ts +function foo() { + // ... +} +export = foo; +``` + +### 多すぎる/少なすぎる引数 + +多すぎる/少なすぎる引数で関数を呼び出していることに気づくことが時々あります。 +通常、これはバグですが、場合によってはパラメータを記述する代わりに`arguments`オブジェクトを使用する関数を宣言しているかもしれません。 + +```js +function myCoolFunction() { + if (arguments.length == 2 && !Array.isArray(arguments[1])) { + var f = arguments[0]; + var arr = arguments[1]; + // ... + } + // ... +} + +myCoolFunction( + function (x) { + console.log(x); + }, + [1, 2, 3, 4] +); +myCoolFunction( + function (x) { + console.log(x); + }, + 1, + 2, + 3, + 4 +); +``` + +この場合、関数のオーバーロードを使って`myCoolFunction`を呼び出すことのできる方法を、呼び出し元に伝えるためにTypeScriptを使用する必要があります。 + +```ts +function myCoolFunction(f: (x: number) => void, nums: number[]): void; +function myCoolFunction(f: (x: number) => void, ...nums: number[]): void; +function myCoolFunction() { + if (arguments.length == 2 && !Array.isArray(arguments[1])) { + var f = arguments[0]; + var arr = arguments[1]; + // ... + } + // ... +} +``` + +2つのオーバーロードシグネチャを`myCoolFunction`に追加しました。 +最初の関数シグネチャは、`myCoolFunction`が(`number`を受け取る)関数を受け取り、次に`number`のリストを受け取ることを示しています。 +二番目は、同様に関数を受け取り、レストパラメータ(`...nums`)を使ってそれ以降の引数は任意の数の`number`である必要があることを示しています。 + +### 順次追加されるプロパティ + +次のように、オブジェクトを作成してその後すぐにプロパティを追加するほうが、審美性が高いと思う人もいます: + +```js +var options = {}; +options.color = "red"; +options.volume = 11; +``` + +TypeScriptは、`options`型をプロパティを持たない`{}`として最初に理解したので、`color`と`volume`を代入できないと言うでしょう。 +プロパティの宣言をオブジェクトリテラルの中に移動させれば、エラーが発生しません: + +```ts +let options = { + color: "red", + volume: 11, +}; +``` + +また、`options`型を定義して、オブジェクトリテラルに型アサーションを追加することができます。 + +```ts +interface Options { + color: string; + volume: number; +} + +let options = {} as Options; +options.color = "red"; +options.volume = 11; +``` + +あるいは、`options`は、`any`型であると指定することもできます。これが最も簡単な方法ですが、メリットは最も少ないです。 + +### `any`、`Object`、そして`{}` + +`Object`は、ほとんどの場合最も一般的な型なので、値に任意の型を持たせるために、`Object`や`{}`を使いたくなるかもしれません。 +しかし、このような場合では **`any`こそ実際に使用したい型**です。というのも、これこそが最も _柔軟な_ 型だからです。 + +例えば、`Object`と型が付けられているものでは、`toLowerCase()`のようなメソッドを呼び出すことはできません。 +より一般的な型であるということは、通常、型でできることは少なくなるということを意味しますが、`any`は最も一般的な型でありながら何でもできるという点で特別です。 +つまり、呼び出したり、コンストラクタとして使えたり、プロパティにアクセスしたりなどができるということです。 +しかし、`any`を使うと常に、TypeScriptが提供するエラーチェックやエディタサポートが失われるということは覚えておいてください。 + +もし、`Object`か`{}`を選ぶことになったら、`{}`を選ぶべきです。 +2つはほとんど同じですが、特定の難解なケースでは`{}`のほうが`Object`より技術的に一般的な型です。 + +## より厳密なチェック + +TypeScriptには、安全性を高めプログラムの解析を向上させるための、あるチェック機能が備わっています。 +ひとたびコードベースをTypeScriptに変換したら、安全性を高めるために、これらのチェックを有効化することができます。 + +### 暗黙的な`any`の禁止 + +TypeScriptがある種の型が何であるかを理解できない場合があります。 +できる限り型の選択肢を緩くするために、TypeScriptは代わりに`any`を使うことになるでしょう。 +この決定はTypeScriptへの移行という点では最適ですが、`any`を使うことは型の安全性が得られないということを意味し、他のところで得られていたツールサポートも得られません。 +`noImplicitAny`を使えば、TypeScriptに対してこうした箇所に印をつけてエラーを出すように指示することができます。 + +### 厳密な`null`と`undefined`チェック + +デフォルトでは、TypeScriptは`null`と`undefined`があらゆるの型の領域にあると仮定しています。 +つまり、`number`型で宣言されたものはすべて`null`や`undefined`になる可能性があるということです。 +`null`や`undefined`はJavaScriptやTypeScriptで頻繁にバグの原因となるため、TypeScriptには`strictNullChecks`オプションがあり、こういった問題を心配するストレスを軽減してくれます。 + +`strictNullChecks`を有効にすると、`null`と`undefined`はそれぞれ`null`と`undefined`という独自の型を取得します。 +何らかの値が`null`である _可能性がある_ 場合は常に元の型とのUnion型を使うことができます。 +例えば、ある値が`number`や`null`になる可能性がある場合、その型を`number | null`と記述します。 + +もし、TypeScriptが`null`/`undefined`の可能性があると考えている値があったとしても、あなたがその可能性がないことを知っている場合は、接尾辞`!`演算子を使って、そう伝えることができます。 + +```ts +declare var foo: string[] | null; + +foo.length; // エラー - 'foo'は'null'の可能性があります + +foo!.length; // OK - 'foo!'は'string[]'型だけです +``` + +注意点として、`strictNullChecks`を使う場合は、同様に`strictNullChecks`を使うように依存関係を更新する必要があるかもしれません。 + +### `this`に対する暗黙的な`any`の禁止 + +クラスの外側で`this`キーワードを使用する場合、デフォルトでは`any`型となります。 +例えば、`Point`クラスがあり、メソッドとして追加したい関数があるとしましょう: + +```ts +class Point { + constructor(public x, public y) {} + getDistance(p: Point) { + let dx = p.x - this.x; + let dy = p.y - this.y; + return Math.sqrt(dx ** 2 + dy ** 2); + } +} +// ... + +// インターフェースを再定義する +interface Point { + distanceFromOrigin(): number; +} +Point.prototype.distanceFromOrigin = function () { + return this.getDistance({ x: 0, y: 0 }); +}; +``` + +これは、前述したものと同じ問題があります - `getDistance`のスペルを間違えてしまうかもしれませんし、その場合エラーも出ません。 +このため、TypeScriptには、`noImplicitThis`オプションがあります。 +このオプションが設定されていれば、TypeScriptは、`this`が明示的な(あるいは推測された)型を持たないで使用された場合、エラーを出します。 +修正するには、`this`パラメータを使ってインターフェースや関数自体の中で明示的な型を与えます。 + +```ts +Point.prototype.distanceFromOrigin = function (this: Point) { + return this.getDistance({ x: 0, y: 0 }); +}; +``` diff --git a/docs/documentation/ja/tutorials/React.md b/docs/documentation/ja/tutorials/React.md new file mode 100644 index 00000000..0f437908 --- /dev/null +++ b/docs/documentation/ja/tutorials/React.md @@ -0,0 +1,26 @@ +--- +title: React +layout: docs +permalink: /ja/docs/handbook/react.html +oneline: TypeScriptとReactについて学ぶためのリンク集 +translatable: true +--- + +TypeScriptは[JSX](/docs/handbook/jsx.html)をサポートしており、`useState`のようなReactコードベースで使用されるパターンを正しくモデル化することができます。 + +### Reactプロジェクトのセットアップ + +今日では、TypeScriptを標準でサポートしているフレームワークがたくさんあります: + +- [Create React App](https://create-react-app.dev) - [TS docs](https://create-react-app.dev/docs/adding-typescript/) +- [Next.js](https://nextjs.org) - [TS docs](https://nextjs.org/learn/excel/typescript) +- [Gatsby](https://www.gatsbyjs.org) - [TS Docs](https://www.gatsbyjs.org/docs/typescript/) + +これらはすべて、プロジェクトの第一歩としてはとても素晴らしいフレームワークです。[このWebサイト](https://github.com/microsoft/TypeScript-Website/)は、TypeScriptと[Gatsby](https://www.gatsbyjs.org/blog/2020-01-23-why-typescript-chose-gatsby/#reach-skip-nav)を使用しており、これも有用な実装の参考となるでしょう。 + +### ドキュメント + +ReactとTypeScriptの最新情報を見つけるのに最適な情報源をここでいくつか紹介します: + +- [React TypeScript Cheatsheets](https://react-typescript-cheatsheet.netlify.app) +- [React & Redux in TypeScript](https://github.com/piotrwitek/react-redux-typescript-guide#react--redux-in-typescript---complete-guide) diff --git a/docs/documentation/ja/tutorials/TypeScript Tooling in 5 minutes.md b/docs/documentation/ja/tutorials/TypeScript Tooling in 5 minutes.md new file mode 100644 index 00000000..73b88afd --- /dev/null +++ b/docs/documentation/ja/tutorials/TypeScript Tooling in 5 minutes.md @@ -0,0 +1,187 @@ +--- +title: 5分でわかるTypeScriptツール +layout: docs +permalink: /ja/docs/handbook/typescript-tooling-in-5-minutes.html +oneline: TypeScriptで小さなウェブサイトを作る方法を理解するためのチュートリアル +translatable: true +--- + +TypeScriptを使って簡単なWebアプリケーションを作ることからはじめてみましょう。 + +## TypeScriptのインストール + +プロジェクトでTypeScriptを利用できるようにするには、主に2つの方法があります: + +- npm(Node.jsのパッケージマネージャー)を使う +- TypeScriptのVisual Studioプラグインをインストールする + +Visual Studio 2017とVisual Studio 2015 Update 3にはTypeScriptがデフォルトで含まれています。 +Visual StudioにTypeScriptをインストールしなかった場合でも、[ダウンロード](/download)は可能です。 + +npmを使う場合はこちら: + +```shell +> npm install -g typescript +``` + +## 初めてのTypeScriptファイルの作成 + +エディタで`greeter.ts`ファイルに次のJavaScriptコードを入力してください: + +```ts twoslash +// @noImplicitAny: false +function greeter(person) { + return "Hello, " + person; +} + +let user = "Jane User"; + +document.body.textContent = greeter(user); +``` + +## コードのコンパイル + +上記で`.ts`拡張子を使いましたが、コードはただのJavaScriptです。 +既存のJavaScriptアプリからそのままコピー/ペーストすることもできます。 + +コマンドラインで、TypeScriptコンパイラを実行します: + +```shell +tsc greeter.ts +``` + +結果は、先ほど入力したJavaScriptと同じものが含まれた`greeter.js`というファイルになります。 +つまり、JavaScriptアプリ上でTypeScriptを実行しているのです! + +これで、TypeScriptが提供する新しいツールを活用できるようになりました。 +次に示すように、関数の引数'person'に対して`: string`という型注釈を付けてみましょう: + +```ts twoslash +function greeter(person: string) { + return "Hello, " + person; +} + +let user = "Jane User"; + +document.body.textContent = greeter(user); +``` + +## 型注釈 + +TypeScriptの型注釈は、関数や変数に対する意図的な制約を記録するための軽量な方法です。 +この例では、greeter関数を単一の文字列パラメータで呼び出すことを意図しています。 +代わりに配列を渡すように、greeterの呼び出しを変更してみましょう: + +```ts twoslash +// @errors: 2345 +function greeter(person: string) { + return "Hello, " + person; +} + +let user = [0, 1, 2]; + +document.body.textContent = greeter(user); +``` + +再コンパイルすると、エラーが表示されます: + +```shell +error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'. +``` + +同様に、greeter関数の呼び出しに渡す引数をすべて削除してみてください。 +TypeScriptは、予期しない数のパラメータを使ってこの関数を呼び出したことを知らせてくれます。 +どちらの場合も、TypeScriptはコードの構造と提供された型注釈に基づいた静的解析を行うことができます。 + +エラーがあったにもかかわらず`greeter.js`ファイルが生成されたことに注意してください。 +コード中にエラーがあってもTypeScriptを使用することはできます。しかし、その場合は、TypeScriptは期待通りに動作しない可能性が高いことを警告しています。 + +## インターフェース + +サンプルをさらに発展させましょう。ここでは、firstNameとlastNameフィールドをもつオブジェクトを記述するインターフェースを使用します。 +TypeScript では、2つの型の内部構造に互換性があれば、それらの型は互換性があるとみなされます。 +このことにより、明示的な`implements`句がなくても、インターフェースが必要とする形状を持つだけで、インターフェースを実装することができます。 + +```ts twoslash +interface Person { + firstName: string; + lastName: string; +} + +function greeter(person: Person) { + return "Hello, " + person.firstName + " " + person.lastName; +} + +let user = { firstName: "Jane", lastName: "User" }; + +document.body.textContent = greeter(user); +``` + +## クラス + +最後に、クラスを使ってこの例をもう一度だけ拡張してみましょう。 +TypeScriptは、クラスベースのオブジェクト指向プログラミングなど、JavaScriptの新しい機能をサポートしています。 + +ここでは、コンストラクタといくつかのpublicフィールドをもつ`Student`クラスを作成します。 +クラスとインターフェースがうまく連携し、プログラマーが適切な抽象度を決定できるようになっていることに注目してください。 + +また、コンストラクタの引数に`public`を使うことが、その名前のプロパティを自動的に作成する省略表現になっていることにも注意してください。 + +```ts twoslash +class Student { + fullName: string; + constructor( + public firstName: string, + public middleInitial: string, + public lastName: string + ) { + this.fullName = firstName + " " + middleInitial + " " + lastName; + } +} + +interface Person { + firstName: string; + lastName: string; +} + +function greeter(person: Person) { + return "Hello, " + person.firstName + " " + person.lastName; +} + +let user = new Student("Jane", "M.", "User"); + +document.body.textContent = greeter(user); +``` + +`tsc greeter.ts`を再実行すると、生成されたJavaScriptが前述のコードと同じであることが確認できます。 +TypeScriptのクラスは、JavaScriptで頻繁に使われているプロトタイプベースのオブジェクト指向プログラミングの単なる省略表現にしかすぎません。 + +## TypeScript の Web アプリを実行 + +`greeter.html`に次のように入力してください: + +```html + + + + TypeScript Greeter + + + + + +``` + +ブラウザで`greeter.html`を開いて、あなたにとって初めてのシンプルなTypeScriptのWebアプリケーションを実行してみましょう! + +任意: `greeter.ts`をVisual Studioで開くか、TypeScriptプレイグラウンドにコードをコピーしてください。 +識別子にマウスをホバーすると、その型が表示されます。 +型が自動的に推測されているケースもあることに注目してください。 +最後の行を再入力すると、DOM要素の型に基づいた補完リストとパラメータのヘルプが表示されます。 +greeter関数の参照にマウスを置いて、F12を押せば、関数の定義に移動します。 +シンボルを右クリックして、名前を変更するリファクタリングツールを使うことができることにも注目してください。 + +提供された型情報は、アプリケーションの規模でJavaScriptを操作するツールと連携して動作します。 +TypeScriptで可能なことのその他の例ついては、Webサイトのサンプルセクションを参照してください。 + +![Visual Studio picture](/images/docs/greet_person.png)