Mam JSON
plik, który wygląda następująco:
{
"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"
}
Próbuję zaimportować go do .tsx
pliku. W tym celu dodałem to do definicji typu:
declare module "*.json" {
const value: any;
export default value;
}
Importuję to w ten sposób.
import colors = require('../colors.json')
W pliku używam koloru primaryMain
jako colors.primaryMain
. Jednak pojawia się błąd:
Właściwość „primaryMain” nie istnieje w typie „typeof„ * .json ”
json
angular
typescript
angular8
Sooraj
źródło
źródło
Odpowiedzi:
Formularz importu i deklaracja modułu muszą być zgodne co do kształtu modułu, co eksportuje.
Podczas pisania (nieoptymalna praktyka importowania JSON od TypeScript 2.9 w przypadku kierowania na zgodne formaty modułów, patrz uwaga )
declare module "*.json" { const value: any; export default value; }
Twierdzisz, że wszystkie moduły, których specyfikator kończy się na,
.json
mają jeden nazwany eksportdefault
.Istnieje kilka sposobów prawidłowego wykorzystania takiego modułu, w tym
import a from "a.json"; a.primaryMain
i
import * as a from "a.json"; a.default.primaryMain
i
import {default as a} from "a.json"; a.primaryMain
i
import a = require("a.json"); a.default.primaryMain
Pierwsza forma jest najlepsza, a cukier składniowy, z którego korzysta, jest przyczyną
default
eksportu JavaScript .Jednak wspomniałem o innych formularzach, aby dać ci wskazówkę, co się dzieje. Zwróć szczególną uwagę na ostatnią.
require
daje obiekt reprezentujący sam moduł, a nie jego wyeksportowane powiązania.Skąd więc błąd? Ponieważ napisałeś
import a = require("a.json"); a.primaryMain
A jednak nie ma żadnego
primaryMain
zadeklarowanego eksportu"*.json"
.Wszystko to zakłada, że moduł ładujący moduł dostarcza JSON jako
default
eksport, zgodnie z sugestią zawartą w pierwotnej deklaracji.Uwaga: Począwszy od TypeScript 2.9, możesz użyć
--resolveJsonModule
flagi kompilatora, aby TypeScript analizował importowane.json
pliki i dostarczał poprawne informacje dotyczące ich kształtu, eliminując potrzebę deklaracji modułu wieloznacznego i weryfikując obecność pliku. Nie jest to obsługiwane w przypadku niektórych formatów modułów docelowych.źródło
await import('remotepath');
Dzięki TypeScript 2.9. + Możesz po prostu importować pliki JSON z zabezpieczeniami typów i inteligencją w następujący sposób:
import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes" console.log(colorsJson.primaryBright);
Pamiętaj, aby dodać te ustawienia w
compilerOptions
sekcji swojejtsconfig.json
( dokumentacji ):"resolveJsonModule": true, "esModuleInterop": true,
Uwagi dodatkowe:
import * as colorsJson from '../colors.json'
źródło
esModuleInterop
, ale musisz to zrobićimport * as foo from './foo.json';
-esModuleInterop
powodowało to inne problemy, gdy próbowałem to włączyć."moduleResolution": "node"
w plikutsconfig.json
. Ma to również wadę, że*.json
pliki, które chcesz zaimportować, muszą znajdować się wewnątrz"rootDir"
. Źródło: blogs.msdn.microsoft.com/typescript/2018/05/31/…import * as foo from './foo.json'
nieprawidłowy formularz importu. Powinno być,import foo = require('./foo.json');
gdy nie używaszesModuleInterop
Jest łatwy w użyciu na maszynie w wersji 2.9+. Możesz więc łatwo importować pliki JSON zgodnie z opisem @kentor .
Ale jeśli potrzebujesz użyć starszych wersji:
Możesz uzyskać dostęp do plików JSON w sposób bardziej TypeScript. Najpierw upewnij się, że nowa
typings.d.ts
lokalizacja jest taka sama, jak w przypadkuinclude
właściwości wtsconfig.json
pliku.Jeśli nie masz właściwości include w swoim
tsconfig.json
pliku. Wtedy struktura folderów powinna wyglądać następująco:Ale jeśli masz
include
nieruchomość w swoimtsconfig.json
:{ "compilerOptions": { }, "exclude" : [ "node_modules", "**/*spec.ts" ], "include" : [ "src/**/*" ] }
Następnie
typings.d.ts
powinieneś znajdować się wsrc
katalogu zgodnie z opisem weinclude
właściwościJak w wielu odpowiedziach, możesz zdefiniować globalną deklarację dla wszystkich swoich plików JSON.
declare module '*.json' { const value: any; export default value; }
ale wolę bardziej wpisaną wersję tego. Na przykład, powiedzmy, że masz
config.json
taki plik konfiguracyjny :{ "address": "127.0.0.1", "port" : 8080 }
Następnie możemy zadeklarować dla niego określony typ:
declare module 'config.json' { export const address: string; export const port: number; }
Łatwo jest zaimportować do plików maszynopisu:
import * as Config from 'config.json'; export class SomeClass { public someMethod: void { console.log(Config.address); console.log(Config.port); } }
Jednak w fazie kompilacji należy ręcznie skopiować pliki JSON do folderu dist. Po prostu dodaję właściwość skryptu do mojej
package.json
konfiguracji:{ "name" : "some project", "scripts": { "build": "rm -rf dist && tsc && cp src/config.json dist/" } }
źródło
W swoim pliku TS Definition, np. Typings.d.ts`, możesz dodać tę linię:
declare module "*.json" { const value: any; export default value; }
Następnie dodaj to w swoim pliku maszynopisu (.ts): -
import * as data from './colors.json'; const word = (<any>data).name;
źródło
any
mówi dwie rzeczy. 1), które zadeklarowałeś lub zaimportowałeś nieprawidłowo, po prostu z definicji. W żadnym wypadku nie powinieneś nigdy potrzebować asercji typu na imporcie modułu, który sam zadeklarowałeś. 2) nawet jeśli masz szalonego modułu ładującego, który jakoś działa w czasie wykonywania, nie daj Boże, nadal byłby to szalenie zagmatwany i najbardziej kruchy sposób na dostęp do modułu o danym kształcie.* as x from
ix from
są jeszcze bardziej niedopasowane pod względem czasu wykonywania niż to, co jest w OP. Poważnie, nie rób tego.Inny sposób
const data: {[key: string]: any} = require('./data.json');
To było nadal możesz zdefiniować typ json, który chcesz i nie musisz używać symboli wieloznacznych.
Na przykład niestandardowy typ json.
interface User { firstName: string; lastName: string; birthday: Date; } const user: User = require('./user.json');
źródło
Często w aplikacjach Node.js wymagany jest plik .json. W przypadku TypeScript 2.9 --resolveJsonModule umożliwia importowanie, wyodrębnianie typów i generowanie plików .json.
Przykład #
// 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 }
źródło
Włącz
"resolveJsonModule": true
wtsconfig.json
pliku i zaimplementuj jak poniżej kod, to działa dla mnie:const config = require('./config.json');
źródło