[解決済み] TypeScriptのカスタムグローバルインターフェース(.d.tsファイル)を設定する方法は?
質問
現在、Webpack2とTypeScriptを使用するReactJSのプロジェクトに取り組んでいます。1つのことを除いて、すべてが完璧に動作します - 私は自分自身で書いたインターフェイスを別のファイルに移動する方法を見つけることができず、それらはアプリケーション全体から見えるようになります。
プロトタイプの目的のために、私は最初にそれらを使用するファイルで定義されたインターフェイスを持っていましたが、最終的に私は複数のクラスで必要とされるものを追加し始め、すべての問題はそこから始まりました。どんな変更をしても
tsconfig.json
にどんな変更を加えても、ファイルをどこに置いても、IDE と Webpack の両方が、名前 (
"Could not find name 'IMyInterface'"
).
以下は、私の現在の
tsconfig.json
ファイルです。
{
"compilerOptions": {
"baseUrl": "src",
"outDir": "build/dist",
"module": "commonjs",
"target": "es5",
"lib": [
"es6",
"dom"
],
"typeRoots": [
"./node_modules/@types",
"./typings"
],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": false,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true
},
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
],
"types": [
"typePatches"
]
}
見ての通り、私の
tsconfig.json
はプロジェクトディレクトリのルートにあり、すべてのソースは
./src
にあり、私はカスタム
.d.ts
ファイルを
./typings
の中に入れて、それを
typeRoots
.
TypeScript 2.1.6と2.2.0でテストしましたが、どちらも動きません。
すべてうまくいくようにする一つの方法は、私の
typings
ディレクトリを
src
というディレクトリを作成し、次に
import {IMyInterface} from 'typings/blah'
を追加することができますが、これは私が使う必要のあるものではないので、私には正しいとは思えません。私は、これらのインターフェイスが、私のアプリケーション全体で「魔法のように」利用可能であってほしいのです。
以下はサンプルです。
app.d.ts
ファイルのサンプルです。
interface IAppStateProps {}
interface IAppDispatchProps {}
interface IAppProps extends IAppStateProps, IAppDispatchProps {}
必要なのは
export
あるいは
declare
? 名前空間でラップする必要がなければいいのですが......。
アップデート(2020年10月)
この質問がまだ驚くほど人気があるのを見て、私は解決策をより詳細に説明したいと思いました。
まず、人々を混乱させる可能性があり、また混乱させるべきことは、私の質問の最後にあげたインターフェースの例には、実際には、どんな
export
キーワードがないことです。あってもなくても変わらないと思って質問には入れなかったのだと思います。まあ、そんなことはないことが判明しており
export
キーワードは、単にインターフェイスを使うことができるか、それとも明示的に
import
を明示する必要があります。
というわけで、TypeScriptでの動作は以下のようになります。
もし、消費モジュールでインポートすることなく、単純に使用できるインターフェースや型が必要な場合、そのインターフェースは
.ts
あるいは、理想的には
.d.ts
ファイル
インポートやエクスポートが同じファイルに存在することなく
. なぜなら、同じファイルから少なくとも 1 つのものをエクスポートするとすぐに、それはモジュールになり、そのモジュールにあるすべてのものは、その後消費者によってインポートされなければならないからです。
という型を持ちたいとします。
Dictionary
という型があり、インポートせずに使えるようにしたいとします。それを宣言する方法は次のようになります。
// types.d.ts
interface Dictionary {}
interface Foo {}
interface Bar {}
使い方は、単純に
// consumer.ts
const dict: Dictionary = {};
しかし、何らかの理由で のいずれかになります。 がエクスポートされた場合、動作しなくなります。
// types.d.ts
interface Dictionary {}
interface Foo {}
export interface Bar {}
また、そのファイルにimportがある場合は動作しません。
// types.d.ts
import { OtherType } from 'other-library';
interface Dictionary {}
interface Foo extends OtherType {}
interface Bar {}
もしそうだとすると、唯一の方法は
Dictionary
を使用する唯一の方法は、それをエクスポートしてコンシューマでインポートすることでしょう。
// types.d.ts
export interface Dictionary {}
interface Foo {}
export interface Bar {}
// consumer.ts
import { Dictionary } from './types';
const dict: Dictionary = {};
--isolatedModules
を使用する際に、さらに気をつけなければならない点があります。
isolatedModules
モジュールフラグは、重要なことに、Create React App - を使用するとデフォルトで有効になります (無効にすることはできません)。
.ts
ファイルでは、少なくとも1つのものをエクスポートしなければなりません。
"All files must be modules when the '--isolatedModules' flag is provided.".このフラグが指定されている場合、すべてのファイルはモジュールでなければなりません。
というエラーが発生します。つまり
Dictionary
インターフェイスを
types.ts
ファイルからエクスポートされたものでなければなりません。それは
.ts
ファイルからのエクスポートでなければなりません。
.d.ts
ファイルに書き出されます。
// types.d.ts
interface Dictionary {} // works
export interface Dictionary {} // works
// types.ts
interface Dictionary {} // doesn't work with --isolatedModules enabled
export interface Dictionary {} // works
N.B.
アンビエントモジュールについては、@dtabuenc さんの回答にもあるように(
.d.ts
ファイル)は不愉快なので、私の訂正はアドバイスとして受け取られるべきではありません。あくまでTypeScriptで通常のモジュールとアンビエントモジュールがどのように動作するかを説明するための試みです。
どのように解決するのか?
魔法のように利用可能なインターフェイスやグローバルな型は非常に推奨されず、ほとんどがレガシーに任されるべきです。 また、アンビエント宣言ファイル (例: d.ts
ファイル) を使うべきではありません。これらは、外部の非typescriptコードの代わりになるものです (本質的には、typescriptの型をjsコードに埋めて、javascriptとよりよく統合できるようにするものです)。
あなたが書くコードには、プレーンな
.ts
ファイルを使って、 インターフェースや型を定義する必要があります。
グローバル型は推奨されませんが、あなたの問題に対する答えは、2つのタイプの
.ts
ファイルです。これらは
scripts
と
modules
.
の中にあるものはすべて
script
にあるものはすべてグローバルになります。つまり、スクリプトでインターフェースを定義すれば、 アプリケーション全体を通してグローバルに利用できるようになります (スクリプトがコンパイル時に
///<reference path="">
タグか
files:[]
または
includes:[]
またはデフォルトの
**/*.ts
の中に
tsconfig.json
.
もう一つのファイルタイプは 'モジュール' で、何でも
module
にあるものはすべてそのモジュールの私的なものです。モジュールから何かをエクスポートした場合、他のモジュールがそれをインポートすることを選択すれば、他のモジュールも利用できるようになります。
何が
.ts
ファイルをスクリプトやモジュールと呼ぶのでしょうか?そうですね......もしあなたが
import/export
を使用している場合、そのファイルはモジュールになります。もし
import/export
ステートメントがない場合、それはグローバルスクリプトになります。
私の推測では、あなたはうっかりと
import
または
export
を宣言してモジュール化すると、そのモジュール内ですべてのインターフェイスがprivateになります。もしグローバルにしたいのであれば、ファイル内でimport/exportステートメントを使用していないことを確認する必要があります。
関連
-
[解決済み】tsconfigファイルにおけるesModuleInteropの理解
-
[解決済み] TypeScriptのハッシュマップ/辞書インターフェイス
-
[解決済み] TypeScriptでグローバル変数を作成する
-
[解決済み] フォーインステートメント
-
[解決済み] TypeScriptで文字列を数値に変換する方法とは?
-
[解決済み] TypeScriptの "*.d.ts "について
-
[解決済み] String型とstring型の違いは何ですか?
-
[解決済み】TypeScriptのインターフェースと型について
-
[解決済み】「エラー TS2533: オブジェクトは 'null' または 'undefined' の可能性があります」を抑制する方法とは?
-
[解決済み】 --isolatedModules のエラーは、どのようなインポートでも修正されるのはなぜですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] TypeScriptの円形型参照
-
[解決済み] Apollo Serverでコンテキストオブジェクトを正しく入力するにはどうすればよいですか?
-
[解決済み] TypeScript - Angular: 複数行の文字列
-
[解決済み] サービスにDocumentを挿入する方法は?
-
[解決済み] TypeScriptでの取得と設定
-
[解決済み] TypeScriptでパラメータとして強く型付けされた関数は可能か?
-
[解決済み] クラス定数を実装するには?
-
[解決済み】オブジェクトの配列を定義するにはどうしたらいいですか?
-
[解決済み】TypeScriptとフィールドイニシャライザー
-
[解決済み】Typescriptのパラメータ名のクエスチョンマークとは?