Импорт json файла в TypeScript

У меня есть JSON файл, который выглядит следующим образом:

{

  "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"
}

Я пытаюсь импортировать его в .tsx файл. Для этого я добавил это к определению типа:

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

И я импортирую его так.

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

И в файле, я использую цвет primaryMain как colors.primaryMain. Однако я получаю сообщение об ошибке - Property 'primaryMain' does not exist on type 'typeof "*.json"

Что я делаю неправильно?

Ответы

Ответ 1

Форма импорта и объявление модуля должны согласовать форму модуля, то, что он экспортирует.

Когда вы пишете (плохая практика для файлов JSON начиная с TypeScript 2.9 при настройке на совместимые форматы модулей see note)

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

Вы заявляете, что все модули, спецификатор которых заканчивается на .json, имеют один экспорт с именем default, который имеет тип any.

Существует несколько способов использования такого модуля, включая

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

и

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

и

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

и

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

Первая форма - лучшая, и синтаксический сахар, который она использует, - это та самая причина, по которой JavaScript экспортирует default.

Однако я упомянул другие формы, чтобы дать вам подсказку о том, что происходит не так. Обратите особое внимание на последний. require дает вам объект, представляющий сам модуль, а не его экспортированные привязки.

Так почему ошибка? Потому что ты написал

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

И все же нет экспорта с именем primaryMain, объявленного вашим "*.json".

Все это предполагает, что ваш загрузчик модулей предоставляет JSON в качестве экспорта default, как предложено в вашей первоначальной декларации.

Примечание: Начиная с TypeScript 2.9, вы можете использовать флаг компилятора --resolveJsonModule, чтобы TypeScript анализировал импортированные файлы .json и предоставлял правильную информацию относительно их формы, устраняя необходимость в объявлении модуля с подстановочными знаками и валидации наличие файла. Это не поддерживается для определенных форматов целевого модуля.

Ответ 2

С TypeScript 2.9. + Вы можете просто импортировать JSON файлы с такими типами безопасности и intellisense, как это:

import colorsJson from '../colors.json';
console.log(colorsJson.primaryBright);

Обязательно добавьте эти параметры в раздел compilerOptions вашего tsconfig.json (документация):

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

Примечания стороны:

  • В Typescript 2.9.0 есть ошибка с этой функцией JSON, я думаю, что она исправлена в 2.9.1 или 2.9.2
  • EsModuleInterop необходим только для импорта по умолчанию colorsJson. Если вы оставите значение false, вам придется импортировать его с помощью import * as colorsJson from '../colors.json'

Ответ 3

Это легко использовать машинописную версию 2. 9+. Таким образом, вы можете легко импортировать JSON файлы в качестве атрибутов @kentor.

Но если вам нужно использовать более старые версии:

Вы можете получить доступ к файлам JSON более чем в режиме TypeScript. Во- первых, убедитесь, что ваш новый typings.d.ts место такое же, как с include свойства в вашем tsconfig.json файле.

Если у вас нет свойства tsconfig.json файле tsconfig.json. Тогда ваша структура папок должна быть такой:

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

Но если у вас есть свойство include в вашем tsconfig.json:

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

Затем ваши typings.d.ts должны находиться в каталоге src как описано в свойстве include

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

Как во многих ответах, вы можете определить глобальное объявление для всех ваших файлов JSON.

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

но я предпочитаю более типичную версию этого. Например, скажем, у вас есть конфигурационный файл config.json:

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

Тогда мы можем объявить для него определенный тип:

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

Легко импортировать в ваши файлы машинописных файлов:

import * as Config from 'config.json';

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

Но на этапе компиляции вы должны вручную скопировать файлы JSON в папку dist. Я просто добавляю свойство script к моей конфигурации package.json:

{
    "name"   : "some project",
    "scripts": {
        "build": "rm -rf dist && tsc && cp src/config.json dist/"
    }
}

Ответ 4

В файле определения TS, например typings.d.ts ', вы можете добавить эту строку:

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

Затем добавьте это в свой файл машинописного текста (.ts): -

import * as data from './colors.json';
const word = (<any>data).name;

Ответ 5

Еще один способ пойти

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

Это было то, что вы все еще можете определить тип json, если хотите, и вам не нужно использовать подстановочный знак.

Например, пользовательский тип JSON.

interface User {
  firstName: string;
  lastName: string;
  birthday: Date;
}
const user: User = require('./user.json');

Ответ 6

Вышесказанное работает, если нет дочерних объектов. если у меня есть JSON, как

{"name": "name", "address": [ { "field1": "value", "field1": "value" }, { "field1": "value", "field1": "value" } ]}

Это не кодирование дочерних объектов JSON.