Ich arbeite derzeit an einem ReactJS-Projekt, das Webpack2 und TypeScript verwendet. Abgesehen von einer Sache funktioniert alles perfekt - ich kann keine Möglichkeit finden, Schnittstellen, die ich selbst geschrieben habe, in separate Dateien zu verschieben, damit sie für die gesamte Anwendung sichtbar sind.
Für Prototyping-Zwecke hatte ich zunächst Schnittstellen in Dateien definiert, die sie verwenden, aber schließlich fügte ich einige hinzu, die in mehreren Klassen benötigt wurden, und dann begannen alle Probleme. tsconfig.json
Unabhängig davon, welche Änderungen ich an meiner vornehme und wo ich die Dateien ablege, beschweren sich meine IDE und mein Webpack darüber, dass sie keine Namen finden können ( "Name 'IMyInterface' konnte nicht gefunden werden" ).
Hier ist meine aktuelle tsconfig.json
Datei:
{
"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"
]
}
Wie Sie sehen können, befindet sich my tsconfig.json
im Stammverzeichnis des Projektverzeichnisses, alle Quellen befinden sich in ./src
, ich habe meine benutzerdefinierten .d.ts
Dateien abgelegt ./typings
und in aufgenommen typeRoots
.
Ich habe es mit TypeScript 2.1.6 und 2.2.0 getestet und beides funktioniert nicht.
Eine Möglichkeit, alles zum Laufen zu bringen, besteht darin, mein typings
Verzeichnis in src
und dann zu verschieben, import {IMyInterface} from 'typings/blah'
aber das fühlt sich für mich nicht richtig an, da ich es nicht verwenden muss. Ich möchte, dass diese Schnittstellen in meiner gesamten Anwendung "magisch" verfügbar sind.
Hier ist eine Beispieldatei app.d.ts
:
interface IAppStateProps {}
interface IAppDispatchProps {}
interface IAppProps extends IAppStateProps, IAppDispatchProps {}
Muss ich export
sie oder vielleicht declare
? Ich hoffe, ich muss sie nicht in einen Namespace einschließen?!
Update (Oktober 2020)
Angesichts der Tatsache, dass diese Frage immer noch überraschend beliebt ist, wollte ich die Lösung genauer erläutern.
Erstens könnte und sollte es für die Leute verwirrend sein, dass das Schnittstellenbeispiel, das ich am Ende meiner Frage gegeben habe, tatsächlich keine export
Schlüsselwörter enthält, obwohl ich fast sicher bin, dass ich sie zum Zeitpunkt der Anfrage in meinen Dateien hatte Frage. Ich glaube, ich habe sie nicht in die Frage aufgenommen, weil ich dachte, sie hätten keinen Unterschied gemacht, ob sie dort waren oder nicht. Nun, es stellt sich heraus, dass es nicht wahr ist und das export
Schlüsselwort genau das ist, was Sie dazu bringt oder bricht, die Schnittstellen einfach "verwenden" zu können, anstatt sie explizit verwenden zu import
müssen.
So funktioniert es in TypeScript wie folgt:
Wenn Sie eine Schnittstelle / einen Typ wünschen, den Sie einfach verwenden können, ohne sie in das konsumierende Modul importieren zu müssen, muss sich diese Schnittstelle in einer .ts
oder idealerweise in einer .d.ts
Datei befinden, ohne dass Importe oder Exporte in derselben Datei vorhanden sind . Dies ist von größter Bedeutung, da sobald Sie mindestens eine Sache aus derselben Datei exportieren, diese zu einem Modul wird und alles, was sich in diesem Modul befindet, anschließend von den Verbrauchern importiert werden muss.
Nehmen wir als Beispiel an, Sie möchten einen Typ namens haben Dictionary
, den Sie ohne Import verwenden können möchten. Die Erklärung wäre wie folgt:
// types.d.ts
interface Dictionary {}
interface Foo {}
interface Bar {}
Um es zu benutzen, tun Sie einfach:
// consumer.ts
const dict: Dictionary = {};
Es funktioniert jedoch nicht mehr, wenn aus irgendeinem Grund eine der Schnittstellen / Typen in dieser Datei exportiert wird, z.
// types.d.ts
interface Dictionary {}
interface Foo {}
export interface Bar {}
Es funktioniert auch nicht, wenn diese Datei Importe enthält:
// types.d.ts
import { OtherType } from 'other-library';
interface Dictionary {}
interface Foo extends OtherType {}
interface Bar {}
Wenn dies der Fall ist, besteht die einzige Möglichkeit, den Dictionary
Typ verwenden zu können, darin, ihn auch zu exportieren und dann in den Verbraucher zu importieren:
// types.d.ts
export interface Dictionary {}
interface Foo {}
export interface Bar {}
// consumer.ts
import { Dictionary } from './types';
const dict: Dictionary = {};
--isolatedModules
Bei der Verwendung des isolatedModules
Modul-Flags in TypeScript ist eine zusätzliche Besonderheit zu beachten , die bei Verwendung von Create React App standardmäßig aktiviert ist (und nicht deaktiviert werden kann). .ts
Dateien MÜSSEN mindestens eine Sache exportieren, da dies sonst der Fall ist die „Alle Dateien müssen Module sein , wenn die‚--isolatedModules‘Flag vorgesehen ist.“ Error. Das bedeutet, dass das Einfügen der Dictionary
Schnittstelle in types.ts
Dateien ohne das Schlüsselwort export nicht funktioniert. Es muss entweder ein Export aus einer .ts
Datei oder eine Deklaration ohne den Export in eine .d.ts
Datei sein:
// types.d.ts
interface Dictionary {} // works
export interface Dictionary {} // works
// types.ts
interface Dictionary {} // doesn't work with --isolatedModules enabled
export interface Dictionary {} // works
NB
Wie @dtabuenc in seiner Antwort erwähnt, sind Umgebungsmodule ( .d.ts
Dateien) nicht korrekt und meine Korrektur sollte nicht als Ratschlag verstanden werden. Es ist nur ein Versuch zu erklären, wie normale Module und Umgebungsmodule in TypeScript funktionieren.
interface Foo {}
Erklärungen hinterlassen habe, hat alles funktioniert. Laut Globals - ich verstehe vollkommen, warum es eine schlechte Praxis ist, Erklärungen magisch verfügbar zu haben, und erwäge, zu einem benutzerdefinierten Modul zu wechseln (tatsächlich versuchtdeclare module MyApp { export interface Foo {} }
und könnte es erfolgreich importierenimport { {Foo} from 'MyApp'
), aber im Moment funktioniert Magie für mich :)SyntheticEvent
Schnittstelle aus React importiert , um sie in meinen eigenen Typdefinitionen zu verwenden, und alles hat aufgehört zu funktionieren. Ich hätte das früher fangen sollen, aber hier sind wir. Vielen Dank!