Importieren einer JSON-Datei in TypeScript

145

Ich habe eine JSONDatei, die wie folgt aussieht:

{

  "primaryBright":    "#2DC6FB",
  "primaryMain":      "#05B4F0",
  "primaryDarker":    "#04A1D7",
  "primaryDarkest":   "#048FBE",

  "secondaryBright":  "#4CD2C0",
  "secondaryMain":    "#00BFA5",
  "secondaryDarker":  "#009884",
  "secondaryDarkest": "#007F6E",

  "tertiaryMain":     "#FA555A",
  "tertiaryDarker":   "#F93C42",
  "tertiaryDarkest":  "#F9232A",

  "darkGrey":         "#333333",
  "lightGrey":        "#777777"
}

Ich versuche es in eine .tsxDatei zu importieren . Dazu habe ich dies der Typdefinition hinzugefügt:

declare module "*.json" {
  const value: any;
  export default value;
}

Und ich importiere es so.

import colors = require('../colors.json')

Und in der Datei verwende ich die Farbe primaryMainals colors.primaryMain. Ich erhalte jedoch eine Fehlermeldung:

Die Eigenschaft 'primaryMain' ist für den Typ 'typeof "* .json" nicht vorhanden.

Sooraj
quelle
3
Ihre Moduldeklaration und Ihr Importformular stimmen nicht überein.
Aluan Haddad
2
Stört es Sie, ein Beispiel zu zeigen? Ich bin Typoskript Noob.
Sooraj
Mögliches Duplikat des Typescript-Compiler-Fehlers beim Importieren der
JSON-

Antworten:

93

Das Importformular und die Moduldeklaration müssen über die Form des Moduls und dessen Export übereinstimmen.

Beim Schreiben (eine suboptimale Vorgehensweise zum Importieren von JSON seit TypeScript 2.9 beim Targeting kompatibler Modulformate siehe Hinweis )

declare module "*.json" {
  const value: any;
  export default value;
}

Sie geben an, dass alle Module, deren Bezeichner mit endet .json, einen einzigen Exportnamen haben . default

Es gibt verschiedene Möglichkeiten, wie Sie ein solches Modul korrekt verwenden können, einschließlich

import a from "a.json";
a.primaryMain

und

import * as a from "a.json";
a.default.primaryMain

und

import {default as a} from "a.json";
a.primaryMain

und

import a = require("a.json");
a.default.primaryMain

Die erste Form ist die beste und der syntaktische Zucker, den sie nutzt, ist genau der Grund, warum JavaScript defaultexportiert.

Ich habe jedoch die anderen Formulare erwähnt, um Ihnen einen Hinweis darauf zu geben, was falsch läuft. Achten Sie besonders auf den letzten. requiregibt Ihnen ein Objekt, das das Modul selbst darstellt und nicht seine exportierten Bindungen.

Warum also der Fehler? Weil du geschrieben hast

import a = require("a.json");
a.primaryMain

Und doch gibt es keinen primaryMainvon Ihnen deklarierten Export "*.json".

All dies setzt voraus, dass Ihr Modullader den JSON als defaultExport bereitstellt, wie in Ihrer ursprünglichen Deklaration vorgeschlagen.

Hinweis: Seit TypeScript 2.9 können Sie das --resolveJsonModuleCompiler-Flag verwenden , damit TypeScript importierte .jsonDateien analysiert und korrekte Informationen zu ihrer Form bereitstellt, sodass keine Platzhaltermoduldeklaration erforderlich ist und das Vorhandensein der Datei überprüft wird. Dies wird für bestimmte Zielmodulformate nicht unterstützt.

Aluan Haddad
quelle
1
@ Royi, das hängt von deinem Lader ab. Für entfernte Dateien sollten Sieawait import('remotepath');
Aluan Haddad
26
Scrollen Sie weiter, aktuellere Antworten finden Sie weiter unten.
jbmusso
@jbmusso Ich habe einige Informationen zu den Verbesserungen hinzugefügt, die durch spätere Versionen von TypeScript eingeführt wurden, aber ich glaube nicht, dass diese Antwort veraltet ist, da sie konzeptionell ist. Ich bin jedoch offen für Vorschläge für weitere Verbesserungen.
Aluan Haddad
1
Das Risiko besteht darin, dass einige Leute einfach die ersten Zeilen Ihrer Antwort kopieren / einfügen und nur das Symptom und nicht die Grundursache beheben. Ich glaube, die Antwort von @ kentor liefert detailliertere und vollständigere Antworten. Eine Empfehlung wäre, Ihre Notiz über Ihre Antwort zu setzen und klar zu sagen, dass dies der richtige Weg ist, um dieses Problem ab heute anzugehen.
Jbmusso
@ Atombit es hat offensichtlich für viele Leute funktioniert, einschließlich mir. Möchten Sie erklären, was nicht funktioniert, bevor Sie die akzeptierte Antwort ablehnen?
Aluan Haddad
266

Mit TypeScript 2.9. + Können Sie einfach JSON-Dateien mit Typensicherheit und Intelligenz wie folgt importieren:

import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes"
console.log(colorsJson.primaryBright);

Stellen Sie sicher, dass Sie diese Einstellungen im compilerOptionsAbschnitt Ihrer tsconfig.json( Dokumentation ) hinzufügen :

"resolveJsonModule": true,
"esModuleInterop": true,

Randnotizen:

  • Typescript 2.9.0 hat einen Fehler mit dieser JSON-Funktion, der mit 2.9.2 behoben wurde
  • Das esModuleInterop ist nur für den Standardimport des FarbenJson erforderlich. Wenn Sie den Wert auf false setzen, müssen Sie ihn mit importierenimport * as colorsJson from '../colors.json'
Kentor
quelle
17
Sie brauchen es nicht unbedingt esModuleInterop, aber dann müssen Sie es tun import * as foo from './foo.json';- das hat esModuleInteropmir andere Probleme bereitet, als ich versucht habe, es zu aktivieren.
Mpen
1
Sie haben Recht, ich hätte das als Randnotiz hinzufügen sollen :-).
Kentor
10
Hinweis: Die Option "resolveJsonModule" kann nicht ohne die Auflösungsstrategie des "Knoten" -Moduls angegeben werden. Sie müssen sie daher auch "moduleResolution": "node"in Ihr Modul aufnehmen tsconfig.json. Es hat auch den Nachteil, dass sich die *.jsonDateien, die Sie importieren möchten, innerhalb befinden müssen "rootDir". Quelle: blogs.msdn.microsoft.com/typescript/2018/05/31/…
Benny Neugebauer
2
@mpen das ist richtig, aber import * as foo from './foo.json'das falsche Importformular. Es sollte sein, import foo = require('./foo.json');wenn nichtesModuleInterop
Aluan Haddad
1
Der einzige Teil, den ich brauchte, war "resolveJsonModule": trueund alles ist gut
Michael Elliott
10

Es ist einfach, Typoskript Version 2.9+ zu verwenden. So können Sie JSON-Dateien einfach als importieren @kentor beschrieben importieren .

Wenn Sie jedoch ältere Versionen verwenden müssen:

Sie können auf mehr TypeScript-Weise auf JSON-Dateien zugreifen. typings.d.tsStellen Sie zunächst sicher, dass Ihr neuer Standort mit dem identisch istinclude Eigenschaft in Ihrer tsconfig.jsonDatei übereinstimmt.

Wenn Ihre tsconfig.jsonDatei keine include-Eigenschaft enthält. Dann sollte Ihre Ordnerstruktur so aussehen:

- app.ts
+ node_modules/
- package.json
- tsconfig.json
- typings.d.ts

Aber wenn Sie eine includeImmobilie in Ihrem tsconfig.json:

{
    "compilerOptions": {
    },
    "exclude"        : [
        "node_modules",
        "**/*spec.ts"
    ], "include"        : [
        "src/**/*"
    ]
}

Dann typings.d.tssollten Sie sich im srcVerzeichnis befinden, wie in includeEigenschaft beschrieben

+ node_modules/
- package.json
- tsconfig.json
- src/
    - app.ts
    - typings.d.ts

Wie in vielen Antworten können Sie eine globale Deklaration für alle Ihre JSON-Dateien definieren.

declare module '*.json' {
    const value: any;
    export default value;
}

aber ich bevorzuge eine typisiertere Version davon. Angenommen, Sie haben eine solche Konfigurationsdatei config.json:

{
    "address": "127.0.0.1",
    "port"   : 8080
}

Dann können wir einen bestimmten Typ dafür deklarieren:

declare module 'config.json' {
    export const address: string;
    export const port: number;
}

Es ist einfach, in Ihre Typoskriptdateien zu importieren:

import * as Config from 'config.json';

export class SomeClass {
    public someMethod: void {
        console.log(Config.address);
        console.log(Config.port);
    }
}

In der Kompilierungsphase sollten Sie JSON-Dateien jedoch manuell in Ihren dist-Ordner kopieren. Ich füge meiner package.jsonKonfiguration einfach eine Skripteigenschaft hinzu:

{
    "name"   : "some project",
    "scripts": {
        "build": "rm -rf dist && tsc && cp src/config.json dist/"
    }
}
Fırat KÜÇÜK
quelle
Ist rm -rf eine Linux / Unix-Sache oder funktioniert das auch auf dem alten Windurz?
Cody
danke, meine typings.d.ts war fehl am platz. Sobald ich nach / src gezogen bin, ist die Fehlermeldung verschwunden.
Gi1ber7
1
@Cody Es ist in der Tat nur eine Linux / Unix-Sache.
Maxie Berkmann
7

In Ihrer TS-Definitionsdatei, z. B. typings.d.ts`, können Sie folgende Zeile hinzufügen:

declare module "*.json" {
const value: any;
export default value;
}

Fügen Sie dies dann in Ihre Typoskriptdatei (.ts) ein: -

import * as data from './colors.json';
const word = (<any>data).name;
Mehadi Hassan
quelle
2
Das ist eine sehr schlechte Idee.
Aluan Haddad
3
Würde es Ihnen etwas ausmachen, bitte erklären Sie, warum es schlecht ist? Ich bin kein Experte für Typoskript. @ AluanHaddad
Mehadi Hassan
5
Ihre Typbehauptung von anysagt zwei Dinge. 1) dass Sie einfach per Definition falsch deklariert oder importiert haben. Sie soll nie unter keinen Umständen braucht eine Art Behauptung auf einem Import eines Moduls platzieren Sie haben selbst erklärt. 2) Selbst wenn Sie einen wahnsinnigen Lader haben, der dies zur Laufzeit irgendwie schafft, Gott sei Dank, wäre es immer noch eine wahnsinnig verwirrende und spröde Art, auf ein Modul der gegebenen Form zuzugreifen. * as x fromund x fromsind in Bezug auf die Laufzeit noch unpassender als im OP. Im Ernst, tu das nicht.
Aluan Haddad
5
Danke für Ihre Antwort. Ich habe klar verstanden. @ AluanHaddad
Mehadi Hassan
2

Ein anderer Weg zu gehen

const data: {[key: string]: any} = require('./data.json');

Hier können Sie immer noch den gewünschten JSON-Typ definieren und müssen keinen Platzhalter verwenden.

Beispiel: Benutzerdefinierter Typ json.

interface User {
  firstName: string;
  lastName: string;
  birthday: Date;
}
const user: User = require('./user.json');
Herr Br
quelle
2
Dies hat nichts mit der Frage zu tun und ist auch eine schlechte Praxis.
Aluan Haddad
0

In Node.js-Anwendungen wird häufig eine .json-Datei benötigt. Mit TypeScript 2.9 ermöglicht --resolveJsonModule das Importieren, Extrahieren von Typen aus und das Generieren von .json-Dateien.

Beispiel #

// tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
}

// .ts

import settings from "./settings.json";

settings.debug === true;  // OK
settings.dry === 2;  // Error: Operator '===' cannot be applied boolean and number


// settings.json

{
    "repo": "TypeScript",
    "dry": false,
    "debug": false
}
von: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

Ruben Palavecino
quelle