Importing JSON Modules in TypeScript

Since TypeScript 2.9 there’s been a `–resolveJsonModule` compiler option that lets us import JSON modules from within TypeScript modules.

Importing JSON Modules via require Calls

Let’s assume we have a Node application written in TypeScript and let’s say that we want to import the following JSON file:

{
  "server": {
    "nodePort": 8080
  }
}

In Node, we can use a require call to import this JSON file like any other CommonJS module:

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

The JSON is deserialized automatically into an everyday JavaScript object. That allows us to access the properties of our config object easily:

"use strict";

const express = require("express");
const config = require("./config.json");

const app = express();

app.listen(config.server.nodePort, () => {
  console.log(`Listening on port ${config.server.nodePort} ...`);
});

Importing JSON Files via Static import Declarations

Let’s now say we want to use native ECMAScript modules instead of CommonJS modules. That means we’ll have to convert all of our require calls to static import declarations:

// All ECMAScript modules implicitly use strict mode.

import * as express from "express";
import * as config from "./config.json";

const app = express();

app.listen(config.server.nodePort, () => {
  console.log(`Listening on port ${config.server.nodePort} ...`);
});

Now, we get a type error on the second line. TypeScript doesn’t let us import a JSON module out of the box, just like that. That was a conscious design decision made by the TypeScript team: pulling in large JSON files could potentially consume a lot of memory, which is why we need to opt into that feature by enabling the –resolveJsonModule compiler flag:

Having people to opt into this consciously would imply the user understands the cost.

Let’s now update our tsconfig.json file and enable the resolveJsonModule:

{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "strict": true,
    "moduleResolution": "node",
    "resolveJsonModule": true
  }
}

With --resolveJsonModule enabled, we no longer get a type error in our TypeScript file. Even better, we now get type checking and autocompletion!

Now, if we compile our TypeScript file with the compiler options shown above, we get the following JavaScript output!

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const express = require("express");
const config = require("./config.json");
const app = express();
app.listen(config.server.nodePort, () => {
    console.log(`Listening on port ${config.server.nodePort} ...`);
});

Now you will see that the output is almost but not quite identical to our initial require version:

"use strict";

const express = require("express");
const config = require("./config.json");

const app = express();

app.listen(config.server.nodePort, () => {
  console.log(`Listening on port ${config.server.nodePort} ...`);
});

And that’s all there is to it! Now you know how to import JSON modules from within TypeScript modules, only one compiler option away.

Latest articles

How to do Destructuring in JavaScript

What is Destructuring? At its core, destructuring is the idea that we are pulling out values individually from a...

Writable Streams, Streams Piping, and Error Handling in Node.js

A Writable Stream A writable stream is a stream of data that is created to write some streaming data....

Here are Six Front-End Development Channels on YouTube

The Coding Train https://www.youtube.com/watch?v=bKEaK7WNLzM If you love programming then this is the...

Real World Use Cases for JavaScript Proxies

Introduction to Proxy In programming terms, a proxy is an entity that acts on behalf of some other entity....
14.0k Followers
Follow

Related articles

Leave a reply

Please enter your comment!
Please enter your name here