Importing JSON file in TypeScript

I have a JSON file that looks like following:

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

I'm trying to import it into a .tsx file. For this I added this to the type definition:

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

And I'm importing it like this.

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

And in the file, I use the color primaryMain as colors.primaryMain. However I get an error:

Property 'primaryMain' does not exist on type 'typeof "*.json"

3

12 Answers

With TypeScript 2.9.+ you can simply import JSON files with benefits like typesafety and intellisense by doing this:

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

Make sure to add these settings in the compilerOptions section of your tsconfig.json (documentation):

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

Side notes:

  • Typescript 2.9.0 has a bug with this JSON feature, it was fixed with 2.9.2
  • The esModuleInterop is only necessary for the default import of the colorsJson. If you leave it set to false then you have to import it with import * as colorsJson from '../colors.json'
8

The import form and the module declaration need to agree about the shape of the module, about what it exports.

When you write (a suboptimal practice for importing JSON since TypeScript 2.9 when targeting compatible module formatssee note)

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

You are stating that all modules that have a specifier ending in .json have a single export named default.

There are several ways you can correctly consume such a module including

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

and

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

and

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

and

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

The first form is the best and the syntactic sugar it leverages is the very reason JavaScript has default exports.

However I mentioned the other forms to give you a hint about what's going wrong. Pay special attention to the last one. require gives you an object representing the module itself and not its exported bindings.

So why the error? Because you wrote

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

And yet there is no export named primaryMain declared by your "*.json".

All of this assumes that your module loader is providing the JSON as the default export as suggested by your original declaration.

Note: Since TypeScript 2.9, you can use the --resolveJsonModule compiler flag to have TypeScript analyze imported .json files and provide correct information regarding their shape obviating the need for a wildcard module declaration and validating the presence of the file. This is not supported for certain target module formats.

5

It's easy to use typescript version 2.9+. So you can easily import JSON files as @kentor decribed.

But if you need to use older versions:

You can access JSON files in more TypeScript way. First, make sure your new typings.d.ts location is the same as with the include property in your tsconfig.json file.

If you don't have an include property in your tsconfig.json file. Then your folder structure should be like that:

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

But if you have an include property in your tsconfig.json:

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

Then your typings.d.ts should be in the src directory as described in include property

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

As In many of the response, You can define a global declaration for all your JSON files.

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

but I prefer a more typed version of this. For instance, let's say you have configuration file config.json like that:

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

Then we can declare a specific type for it:

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

It's easy to import in your typescript files:

import * as Config from 'config.json'; export class SomeClass { public someMethod: void { console.log(Config.address); console.log(Config.port); } } 

But in compilation phase, you should copy JSON files to your dist folder manually. I just add a script property to my package.json configuration:

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

Here's how to import a json file at runtime

import fs from 'fs' var dataArray = JSON.parse(fs.readFileSync('data.json', 'utf-8')) 

This way you avoid issues with tsc slowing down or running out of memory when importing large files, which can happen when using resolveJsonModule.

2

You should add

"resolveJsonModule": true 

as part of compilerOptions to tsconfig.json.

Often in Node.js applications a .json is needed. With TypeScript 2.9, --resolveJsonModule allows for importing, extracting types from and generating .json files.

Example #

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

by: 1

Another way to go

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

This was you still can define json type is you want and don't have to use wildcard.

For example, custom type json.

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

In an Angular (typescript) app, I needed to include a .json file in my environment.ts. To do so, I had to set two options in tsconfig:

{ "compilerOptions": { "moduleResolution": "node", "resolveJsonModule": true } } 

Then, I could import my json file into the environment.ts:

import { default as someObjectName } from "../some-json-file.json"; 

In my case I needed to change tsconfig.node.json:

{ "compilerOptions": { ... "resolveJsonModule": true }, "include": [..., "colors.json"] } 

And to import like that:

import * as colors from './colors.json' 

Or like that:

import colors from './colors.json' 

with "esModuleInterop": true

Enable "resolveJsonModule": true in tsconfig.json file and implement as below code, it's work for me:

const config = require('./config.json'); 

Note that if you using @kentor ways

Make sure to add these settings in the compilerOptions section of your tsconfig.json (documentation):

You need to add --resolveJsonModule and--esModuleInterop behind tsc command to compile your TypeScript file.

Example: tsc --resolveJsonModule --esModuleInterop main.ts

in my case I had to change: "include": ["src"] to "include": ["."] in addition to "resolveJsonModule":true because I tried to import manifest.json from the root of the project and not from ./src

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like