Skip to content

Commit 742bacc

Browse files
committed
anyの説明とeslint-disable-next-lineの用法を追加
1 parent 0c629b7 commit 742bacc

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

typing.rst

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,19 @@ JavaScriptは動的言語の中でも、いろいろ制約がゆるく、無名
3333
console.log(opts.debug); // debugがあるかどうかチェックしないのでエラーにならない
3434
}
3535
36-
これを積極的に使う場面はというと、すでにJavaScriptとして動作していて実績があるコードをTypeScriptにまずは持ってくる、というケースが考えられます。
36+
ただし、これを使うと、TypeScriptが提供する型チェックの恩恵は受けられません。\ ``any``\ から型情報つきのデータにするためには後述の型ガードや型アサーションで変換しなければなりません。利用する箇所で毎回必要になります。TypeScriptの型情報は伝搬するので、なるべく早めに、データが発生する場所で型情報を付ければ、変換が不要になります。そのため、よっぽどの理由がないかぎりは\ ``any``\ を使わない方がトータルの実装コストは大きく減ります。実際にTypeScriptできちんと回っているプロジェクトの場合、ESLintで\ ``any``\ を使っていたらエラーにすることになるでしょう。
37+
38+
``any``\ を積極的に使う場面は2つあります。
39+
40+
1つは後述するユーザー定義の型ガードの引数です。これは「型がわからないデータの型を診断する」関数ですので、引数は\ ``any``\ となります。
41+
42+
それ以外だと、外部からやってくるデータなどはコンパイル時には型情報がわかりません。標準ライブラリのブラウザのサーバーアクセスAPIの\ ``fetch``\ のレスポンスの\ ``json()``\ メソッドの返り値は\ ``any``\ となっています。そのため、\ ``fetch``\ のレスポンスに関しては何かしらの変換処理が必要になります。ただし、このケースは\ ``any``\ が利用されているだけでユーザーコードの中で\ ``any``\ とタイプすることはありません。
43+
44+
消極的な利用方法としては、すでにJavaScriptとして動作していて実績があるコードをTypeScriptにまずは持ってくる、というケースが考えられます。
3745
あとは、メインの引数ではなくて、挙動をコントロールするオプションの項目がかなり複雑で、型定義が複雑な場合などです。
3846
例えば、JSONSchemaを受け取るような引数があったら、JSONSchemaのすべての仕様を満たす型定義を記述するのはかなり時間を要します。
3947
将来やるにしても、まずはコンパイルだけは通したい、というときに使うと良いでしょう。
4048

41-
ただし、これを使うと、TypeScriptが提供する型チェックの恩恵は受けられません。\ ``any``\ から型情報つきのデータにするためには後述の型ガードや型アサーションで変換しなければなりません。利用する箇所で毎回必要になります。TypeScriptの型情報は伝搬するので、なるべく早めに、データが発生する場所で型情報を付ければ、変換が不要になります。そのため、よっぽどの理由がないかぎりは\ ``any``\ を使わない方がトータルの実装コストは大きく減ります。
42-
43-
それ以外だと、外部からやってくるデータなどはコンパイル時には型情報がわかりません。標準ライブラリのブラウザのサーバーアクセスAPIの\ ``fetch``\ のレスポンスは\ ``any``\ となっています。そのため、\ ``fetch``\ のレスポンスに関しては何かしらの変換処理が必要になります。
4449

4550
未知の型: ``unknown``
4651
------------------------------
@@ -430,6 +435,7 @@ TypeScriptのベースになっているJavaScriptでは、長らくオブジェ
430435
.. code-block:: ts
431436
:caption: ユーザー定義の型ガード
432437
438+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
433439
function isArray(arg: any): arg is Array {
434440
return Array.isArray(arg);
435441
}
@@ -438,6 +444,7 @@ TypeScriptのベースになっているJavaScriptでは、長らくオブジェ
438444
* 引数は ``arg: any``
439445
* 返り値の型は ``arg is Array``
440446
* 関数の返り値は、型ガードの条件が満たされる実行文
447+
* たいていのプロジェクトではESLintで\ ``any``\ はエラーにしていると思うので、ここだけ明示的に使うために警告を抑制
441448

442449
なんども説明している通り、型ガードではTypeScriptのコンパイラだけが知っている情報は扱えません。JavaScriptとして実行時にアクセスできる情報( ``Array.isArray()`` のような関数、 ``typeof`` 、 ``instanceof`` 、 ``in`` 、比較などあらゆる方法を駆使)を使って、booleanを返す必要があります。
443450

@@ -557,7 +564,7 @@ TypeScriptは既存のJavaScriptの使い方のすべてをカバーできるよ
557564
通常であれば外部からの入出力や関数の入り口の宣言程度で済むはずで、実装コードの中の大部分は明示的に型を指定しなくても、推論で終了することが多いです。それでも済まないのは主に4つの理由が考えられます。
558565

559566
1. 利用するライブラリがTypeScriptの型定義ファイルを用意していないケース。近年ではどんどん減っていますが、もし用意されていないのであれば型定義を自分で起こしたり、関数のレスポンスに自分で型定義を行う必要があるため、手間が増えます。
560-
2. ライブラリの使用方法がTypeScriptフレンドリーではないケース。Redux-Toolkitではない通常のReduxでは、ステートやアクションの型定義を利用者側が細かく用意しなければなりません。Reactもクラスコンポーネントよりは関数コンポーネントの方が開発者が設定しなければならない型注釈は少なくて済みます。JavaScript時代に作られたライブラリによってはTypeScriptの型推論が効きにくいことがあります。
567+
2. ライブラリの使用方法がTypeScriptフレンドリーではないケース。Redux-Toolkitではない通常のReduxでは、ステートやアクションの型定義を利用者側が細かく用意しなければなりません。Reactもクラスコンポーネントよりは関数コンポーネントの方が開発者が設定しなければならない型注釈は少なくて済みます。JavaScript時代に作られたライブラリによってはTypeScriptの型推論が効きにくいことがあります。例えば、SwaggerやOpenAPIで型定義を行っているケースで、requiredが適切に付与されていないと、すべての属性が\ ``| undefined``\ 付きになります。不要なOptionalは、型ガードやアサーションが大量に必要になります。
561568
3. 同一の変数に多様な型のものを入れようとしていたり、関数の引数や返り値も多様なものを返しているケース。\ ``null``\ か何かしらのインスタンスか、ぐらいであれば、その関数の内部の実装や、利用者側のコードで型注釈が必要になることはごくまれです。特に返り値の型の種類が多様になる場合は要注意です。
562569
4. 多様な型を取り扱うためにジェネリクスなどの高度な型定義が必要になるケース。3のケースに付随してそれをカバーするためのコードが複雑になる場合です。
563570

0 commit comments

Comments
 (0)