1. ホーム
  2. typescript

[解決済み] TypeScript 2: 型付けされていない npm モジュールのためのカスタム型付け

2023-02-08 17:28:59

質問

で投稿された提案を試した後 他の場所 に投稿された提案を試した後、私はタイプされていないNPMモジュールを使用するtypescriptプロジェクトを実行することができないことに気がつきました。以下は、最小限の例と私が試した手順です。

この最小限の例では、次のように仮定します。 lodash は既存の型定義を持っていないことにします。そのため、パッケージ @types/lodash を無視し,その型付けファイルを手動で lodash.d.ts をプロジェクトに追加してみます。

フォルダの構造

  • ノードモジュール
    • ロダッシュ
  • src
    • foo.ts
  • 型付け
    • カスタム
      • lodash.d.ts
    • グローバル
    • index.d.ts
  • パッケージ.json
  • tsconfig.json
  • タイピング.json

次に、ファイルです。

ファイル foo.ts

///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from 'lodash';

console.log('Weeee');

ファイル lodash.d.ts はそのままコピーされ、元の @types/lodash パッケージから直接コピーされます。

ファイル index.d.ts

/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />

ファイル package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "typings": "./typings/index.d.ts",
  "dependencies": {
    "lodash": "^4.16.4"
  },
  "author": "",
  "license": "ISC"
}

ファイル tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "typeRoots" : ["./typings"],
    "types": ["lodash"]
  },
  "include": [
    "typings/**/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

ファイル typings.json

{
    "name": "TestName",
    "version": false,
    "globalDependencies": {
        "lodash": "file:typings/custom/lodash.d.ts"
    }
}

ご覧のように、型付けをインポートする方法をいろいろと試してみました。

  1. で直接インポートすることで foo.ts
  2. によって typings のプロパティで package.json
  3. を使用することで typeRootstsconfig.json というファイルに対して typings/index.d.ts
  4. 明示的な typestsconfig.json
  5. を含めることで types ディレクトリを tsconfig.json
  6. をカスタムで作成することで typings.json ファイルを作成し typings install

なのに、Typescriptを実行すると

E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

私は何を間違えているのでしょうか?

どうすればいいのでしょうか?

残念ながらこれらのことは現在あまり文書化されていませんが、仮に動作させることができたとしても、各パーツが何をしているのか、そしてそれがどのように typescript が typing を処理しロードするかにどう関係しているのかを理解するために、設定を確認してみましょう。

まず、あなたが受け取ったエラーについて説明します。

error TS2688: Cannot find type definition file for 'lodash'.

このエラーは、実はインポートや参照、あるいはtsファイルのどこかでlodashを使おうとしていることが原因ではありません。むしろ、これは typeRootstypes プロパティがあるので、それらについてもう少し詳しく見ていきましょう。

についてですが typeRoots:[]types:[] のプロパティは、それらが ではない 任意の宣言を読み込むための汎用的な方法 ( *.d.ts ) ファイルを読み込む汎用的な方法です。

この2つのプロパティは、TS 2.0の新機能に直接関連しており、型付け宣言を NPM パッケージ .

これは非常に重要なことで、これらは NPM フォーマットのフォルダ (すなわち、"em" を含むフォルダ) に対してのみ動作することを理解してください。 package.json または index.d.ts ).

のデフォルトは typeRoots です。

{
   "typeRoots" : ["node_modules/@types"]
}

デフォルトでは、これはtypescriptが node_modules/@types フォルダに入り、そこで見つけたすべてのサブフォルダを npm パッケージ .

フォルダがnpmパッケージのような構造を持っていない場合、これは失敗することを理解することが重要です。

これが、あなたのケースで起こっていることであり、最初のエラーの原因です。

typeRootをbeに切り替えています。

{
    "typeRoots" : ["./typings"]
}

これは、typescript が ./typings フォルダをスキャンして サブフォルダ で、見つかった各サブフォルダをnpmモジュールとして読み込もうとします。

では、先ほど typeRoots を指すように設定したとします。 ./typings を指すように設定されていますが、まだ types:[] プロパティがセットアップされていません。このようなエラーが表示される可能性があります。

error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.

これは tsc をスキャンしているからです。 ./typings フォルダをスキャンし、サブフォルダ customglobal . そして、これらをnpmパッケージタイプのタイピングとして解釈しようとしている。 index.d.ts または package.json というフォルダがあるため、このようなエラーが発生します。

さて、ここで少し types: ['lodash'] プロパティについて少し説明します。これは何をするものなのでしょうか?デフォルトでは、typescript は をすべて サブフォルダを読み込みます。 typeRoots . を指定すると types: プロパティを指定すると、それらの特定のサブフォルダのみが読み込まれます。

この例では ./typings/lodash フォルダを読み込むように指示していますが、それは存在しません。このため、次のようになります。

error TS2688: Cannot find type definition file for 'lodash'

では、学んだことをまとめてみましょう。Typescript 2.0 が導入された typeRootstypes にパッケージされた宣言ファイルを読み込むために npm パッケージ . もし、カスタム型付けや単一の緩い d.ts ファイルがあり、それが npm パッケージの規約に従ったフォルダに含まれていない場合、これら 2 つの新しいプロパティは使うべきものではありません。Typescript 2.0 は、これらのファイルがどのように消費されるかを実際に変更することはありません。ただ、これらのファイルを、多くの標準的な方法でコンパイルコンテキストにインクルードする必要があります。

  1. で直接インクルードする。 .ts ファイルに記述します。 ///<reference path="../typings/custom/lodash.d.ts" />

  2. 含む ./typings/custom/lodash.d.ts の中に files: [] プロパティに追加します。

  3. 含む ./typings/index.d.ts の中に files: [] プロパティに追加します (これにより、他の型付けも再帰的に含まれます)。

  4. 追加する ./typings/**includes:

うまくいけば、この議論に基づいて、あなたの tsconfig.json を変更したことで、再び動作するようになった理由を説明できるようになるとよいのですが。

EDITです。

ひとつ言い忘れていたのは typeRootstypes プロパティは、実際には 自動 ロードのためにのみ有用です。

例えば、もしあなたが

npm install @types/jquery

また、デフォルトのtsconfigを使用している場合、そのjquery typesパッケージは自動的にロードされ $ はすべてのスクリプトで利用可能であり、それ以上 ///<reference/> または import

typeRoots:[] プロパティは、追加の場所を追加するためのもので、そこからタイプ パッケージ が自動的に読み込まれる場所を追加するものです。

この types:[] プロパティの主な用途は、(空の配列に設定することで)自動ロードの動作を無効にし、グローバルに含めたい特定のタイプのみをリストアップすることです。

型パッケージをロードする他の方法として、様々な typeRoots は、新しい ///<reference types="jquery" /> ディレクティブを使うことです。注目すべきは types ではなく path . 繰り返しますが、これはグローバルな宣言ファイルに対してのみ有効であり、典型的なものは import/export .

さて、ここで、混乱を招くもののひとつが typeRoots . 覚えていますか、私が言ったのは typeRoots はモジュールのグローバルインクルードについてだと言ったことを思い出してください。しかし @types/folder は標準的なモジュール解決にも関わってきます (あなたの typeRoots の設定に関係なく)。

具体的には、モジュールを明示的にインポートすることで、常にすべての includes , excludes , files , typeRootstypes というオプションがあります。 だから、そうすると

import {MyType} from 'my-module';

上記のプロパティはすべて完全に無視されます。の間に関連するプロパティは モジュール解決 baseUrl , paths そして moduleResolution .

基本的に node モジュール解決では、ファイル名の検索を開始します。 my-module.ts , my-module.tsx , my-module.d.ts で指定されたフォルダを起点に baseUrl の設定によって指定されたフォルダを開始します。

もしファイルが見つからなければ、次のような名前のフォルダを探します。 my-module という名前のフォルダを探し、さらに package.json を持つ typings プロパティがある場合、もし package.json がない場合、または typings プロパティがない場合、どのファイルを読み込むかを指定すると、そのファイルは index.ts/tsx/d.ts を探します。

それでもうまくいかない場合は、同じものを node_modules フォルダを探します。 baseUrl/node_modules .

さらに、これらが見つからなければ、次のように検索します。 baseUrl/node_modules/@types を検索します。

それでも見つからない場合は、親ディレクトリに移動して検索します。 node_modulesnode_modules/@types といった具合です。ファイルシステムのルートに到達するまで、ディレクトリを上り続けます(プロジェクト外のノードモジュールも取得します)。

ひとつ強調しておきたいのは、モジュールの解決はどんな typeRoots が設定されていても、完全に無視されるということです。ですから、もしあなたが typeRoots: ["./my-types"] を設定した場合、これは明示的なモジュール解決中に検索されることはありません。これは、インポートや参照を必要とせずにアプリケーション全体が利用できるようにしたいグローバル定義ファイルを置くためのフォルダとしてのみ機能します。

最後に、パスマッピングでモジュールの動作をオーバーライドすることができます (すなわち paths プロパティ) を使ってモジュールの動作を上書きすることができます。ですから、たとえば、任意のカスタム typeRoots は参照されないと書きました。しかし、もしあなたが好きなら、この動作を次のように実現することができます。

"paths" :{
     "*": ["my-custom-types/*", "*"]
 }

これは何をするかというと、左辺にマッチするすべてのインポートに対して、右辺のようにインポートを変更してから、それをインクルードしようとします(その際に * は最初のインポート文字列を表しています。たとえば、あなたがインポートした場合。

import {MyType} from 'my-types';

と書いたかのように、まずインポートを試します。

import {MyType} from 'my-custom-types/my-types'

そして、もし見つからなかったら、接頭辞なしで再試行します(配列の2番目の項目は単に * で、これは最初のインポートを意味します。

このように、カスタム宣言ファイルを検索するためのフォルダを追加したり、あるいはカスタム .ts モジュールを検索することができます。 import .

また、特定のモジュールのためのカスタムマッピングを作成することもできます。

"paths" :{
   "*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
 }

これによって

import {MyType} from 'my-types';

しかし、次にこれらの型を some/custom/folder/location/my-awesome-types-file.d.ts