他の場所 に投稿された提案を試した後、型指定されていないNPMモジュールを使用するTypeScriptプロジェクトを実行できません。以下は最小限の例と私が試した手順です。
この最小限の例では、lodash
に既存の型定義がないと仮定します。そのため、パッケージ@types/lodash
を無視し、そのタイピングファイルlodash.d.ts
をプロジェクトに手動で追加しようとします。
フォルダー構造
次に、ファイル。
ファイル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"
}
}
ご覧のとおり、タイピングをインポートするさまざまな方法を試しました。
foo.ts
に直接インポートすることによりpackage.json
のtypings
プロパティによってtsconfig.json
でtypings/index.d.ts
のtypeRoots
を使用するtsconfig.json
で明示的なtypes
を使用することによりtsconfig.json
にtypes
ディレクトリを含めることによりtypings.json
ファイルを作成し、typings install
を実行するそれでも、TypeScriptを実行すると:
E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.
何が間違っていますか?
残念ながら、これらのことは現在あまりよく文書化されていませんが、それを機能させることができたとしても、各部分が何をしているのか、TypeScriptがタイピングをどのように処理しロードするかとどう関係するのかを理解するために設定を見ていきましょう。
最初に、受信しているエラーを調べてみましょう。
error TS2688: Cannot find type definition file for 'lodash'.
このエラーは、実際には、インポートまたは参照、またはtsファイル内のどこでもlodashを使用しようとしたことが原因ではありません。むしろ、typeRoots
プロパティとtypes
プロパティの使用方法の誤解から来ているので、それらについてもう少し詳しく見ていきましょう。
typeRoots:[]
およびtypes:[]
プロパティに関することは、これらがではなくの任意の宣言(*.d.ts
)ファイルをロードする汎用的な方法であることです。
これら2つのプロパティは、NPM packagesから入力宣言をパッケージ化およびロードできる新しいTS 2.0機能に直接関連しています。
これは、NPM形式のフォルダー(つまりpackage.jsonまたはindex.d.ts)。
typeRoots
のデフォルトは次のとおりです。
{
"typeRoots" : ["node_modules/@types"]
}
デフォルトでは、これはTypeScriptがnode_modules/@types
フォルダーに入り、そこで見つかったすべてのサブフォルダーをnpm packageとしてロードしようとすることを意味します。
フォルダーにnpmパッケージのような構造がない場合、これは失敗することを理解することが重要です。
これがあなたのケースで起こっていることであり、初期エラーの原因です。
TypeRootを次のように切り替えました。
{
"typeRoots" : ["./typings"]
}
これは、TypeScriptが./typings
フォルダーでsubfoldersをスキャンし、見つかった各サブフォルダーをnpmモジュールとしてロードしようとすることを意味します。
それでは、./typings
を指すtypeRoots
のセットアップがあったが、まだtypes:[]
のプロパティがセットアップされていないふりをしましょう。次のエラーが表示される可能性があります。
error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.
これは、tsc
が./typings
フォルダーをスキャンして、サブフォルダーcustom
およびglobal
を検出しているためです。次に、これらをnpmパッケージタイプのタイピングとして解釈しようとしていますが、これらのフォルダーにはindex.d.ts
またはpackage.json
がないため、エラーが発生します。
ここで、設定しているtypes: ['lodash']
プロパティについて少し話しましょう。これは何をしますか?デフォルトでは、TypeScriptは、typeRoots
内で見つかったallサブフォルダーをロードします。 types:
プロパティを指定すると、それらの特定のサブフォルダーのみが読み込まれます。
あなたの場合、./typings/lodash
フォルダーをロードするように伝えていますが、存在しません。これがあなたが得る理由です:
error TS2688: Cannot find type definition file for 'lodash'
それで、私たちが学んだことを要約しましょう。 TypeScript 2.0では、npm packagesにパッケージ化された宣言ファイルをロードするためのtypeRoots
およびtypes
が導入されました。 npmパッケージの規則に従ってフォルダーに含まれていないカスタムタイピングまたは単一の緩いd.ts
ファイルがある場合、これらの2つの新しいプロパティは使用するものではありません。 TypeScript 2.0は、これらの消費方法を実際には変更しません。多くの標準的な方法のいずれかで、これらのファイルをコンパイルコンテキストに含める必要があります。
.ts
ファイルに直接含める:///<reference path="../typings/custom/lodash.d.ts" />
./typings/custom/lodash.d.ts
プロパティにfiles: []
を含める。
./typings/index.d.ts
プロパティにfiles: []
を含める(その後、他のタイピングを再帰的に含みます)。
./typings/**
をincludes:
に追加する
この議論に基づいて、tsconfig.json
に変更を加えたことが原因で再び機能するようになった理由がわかることを願っています。
私が言及するのを忘れていた1つのことは、typeRoots
とtypes
プロパティは、グローバル宣言の自動ロードにのみ実際に有用であることです。
たとえば
npm install @types/jquery
そして、デフォルトのtsconfigを使用している場合、jqueryタイプのパッケージが自動的にロードされ、$
は///<reference/>
またはimport
をさらに行う必要のないすべてのスクリプトで利用可能になります
typeRoots:[]
プロパティは、タイプpackagesが自動的に読み込まれる場所を追加することを目的としています。
types:[]
プロパティの主な使用例は、自動ロード動作を無効にして(空の配列に設定することにより)、グローバルに含めたい特定のタイプのみをリストすることです。
さまざまなtypeRoots
から型パッケージをロードする別の方法は、新しい///<reference types="jquery" />
ディレクティブを使用することです。 types
ではなくpath
に注意してください。繰り返しますが、これはグローバルな宣言ファイル、通常はimport/export
を実行しないファイルにのみ役立ちます。
ここで、typeRoots
との混乱を引き起こすものの1つを示します。 typeRoots
はモジュールのグローバルな包含に関するものだと言ったことを思い出してください。ただし、@types/folder
は標準モジュールの解決にも関係します(typeRoots
設定に関係なく)。
具体的には、モジュールを明示的にインポートすると、常にincludes
、excludes
、files
、typeRoots
、およびtypes
オプションがすべてバイパスされます。あなたがそうするとき:
import {MyType} from 'my-module';
上記のプロパティはすべて完全に無視されます。 モジュール解決中の関連プロパティは、baseUrl
、paths
、およびmoduleResolution
です。
基本的に、node
モジュール解決を使用する場合、baseUrl
構成で指定されたフォルダーからファイル名my-module.ts
、my-module.tsx
、my-module.d.ts
の検索を開始します。
ファイルが見つからない場合は、my-module
という名前のフォルダーを探し、typings
プロパティを持つpackage.json
を検索します。package.json
が存在する場合、またはtypings
プロパティをロードするファイルを指定すると、index.ts/tsx/d.ts
が検索されますそのフォルダ内。
それでもうまくいかない場合は、node_modules
で始まるbaseUrl/node_modules
フォルダーで同じものを検索します。
さらに、これらが見つからない場合は、baseUrl/node_modules/@types
で同じものをすべて検索します。
それでも何も見つからなかった場合は、親ディレクトリに移動し、node_modules
とnode_modules/@types
を検索します。ファイルシステムのルートに到達するまでディレクトリを上に移動し続けます(プロジェクトの外にノードモジュールを取得することもあります)。
私が強調したいことの1つは、モジュールの解決は、設定したtypeRoots
を完全に無視することです。したがって、typeRoots: ["./my-types"]
を構成した場合、明示的なモジュール解決中にこれは検索されません。インポートまたは参照することなく、アプリケーション全体で使用できるようにするグローバル定義ファイルを配置できるフォルダーとしてのみ機能します。
最後に、パスマッピング(つまり、paths
プロパティ)でモジュールの動作をオーバーライドできます。したがって、たとえば、モジュールを解決しようとするときに、カスタムtypeRoots
は参照されないことに言及しました。しかし、もしあなたが好きなら、この動作を次のように実行できます
"paths" :{
"*": ["my-custom-types/*", "*"]
}
これは、左側と一致するすべてのインポートに対して行われます。インポートを含める前に、右側のようにインポートを変更してみてください(右側の*
は、最初のインポート文字列を表します。たとえば、インポートする場合:
import {MyType} from 'my-types';
あなたが書いたように最初にインポートを試みます:
import {MyType} from 'my-custom-types/my-types'
そして、それが見つからなかった場合、接頭辞なしで再試行します(配列の2番目の項目は、最初のインポートを意味する*
です。
したがって、この方法では、追加のフォルダーを追加して、カスタム宣言ファイル、またはimport
にしたいカスタム.ts
モジュールを検索できます。
特定のモジュールのカスタムマッピングを作成することもできます。
"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
から読み取ります
編集:古い。上記の答えを読んでください。
私はまだこれを理解していませんが、解決策を見つけました。次のtsconfig.json
を使用します。
{
"compilerOptions": {
"target": "ES6",
"jsx": "react",
"module": "commonjs",
"sourceMap": true,
"noImplicitAny": true,
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"*": [
"./typings/*"
]
}
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
typings.json
と、lodash.d.ts
を除くフォルダーtypings
の下のすべてを削除します。すべての///...
参照も削除します
"*": ["./types/*"]
tsconfigパスのこの行は、2時間の闘争の後、すべてを修正しました。
{
"compilerOptions": {
"moduleResolution": "node",
"strict": true,
"baseUrl": ".",
"paths": {
"*": ["./types/*"]
},
"jsx": "react",
"types": ["node", "jest"]
},
"include": [
"client/**/*",
"packages/**/*"
],
"exclude": [
"node_modules/**/*"
]
}
typesは、node_moduleの横にあるフォルダー名です。つまり、clientフォルダー(またはのレベル) srcフォルダー)types/third-party-lib/index.d.ts
index.d.tsにはdeclare module 'third-party-lib';
があります
注:上記の設定は不完全な設定であり、タイプ、パス、インクルードおよびエクスクルードでどのように見えるかのアイデアを提供するだけです。