How to import JSON files in TypeScript

Updated: January 8, 2024 By: Guest Contributor Post a comment

Introduction

TypeScript, being a superset of JavaScript, allows importing JSON files natively, the same way you would in JavaScript. However, with its type-checking benefits, you may need to define typings for your JSON data. In this tutorial, we’ll walk through the process of importing JSON files in a TypeScript project with examples ranging from basic to advanced techniques.

Prerequisites:

  • A basic understanding of TypeScript
  • Node.js and npm installed
  • A TypeScript project setup

Setting Up TypeScript to Import JSON

Before diving into code examples, make sure that your TypeScript configuration file (tsconfig.json) includes the following settings:

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

resolveJsonModule allows TypeScript to recognize JSON imports. esModuleInterop permits default imports from modules with no default export.

Importing a Basic JSON File

// Example: Importing a simple JSON file in TypeScript
import myData from './data.json';

console.log(myData);

This will log the content of data.json to the console.

Typing the Imported JSON Data

// Define an interface for the JSON structure
interface MyData {
  id: number;
  name: string;
}

// Import JSON file with typings
import myData from './data.json' assert {type: 'json'} as MyData;

console.log(myData.id);  // Reading an id property, knowing it exists

Using TypeScript’s type system, we can define the structure which our JSON should adhere to by declaring an interface.

Handling Dynamic JSON Structures

When dealing with JSON files that have dynamic structures, you can use types like any, unknown, or even a union type to represent your data:

// Importing JSON with unknown or dynamic structure
import myDynamicData from './dynamicData.json' assert {type: 'json'};

if (typeof myDynamicData === 'object' && myDynamicData !== null) {
  // Handle the JSON object
}

It’s recommended to avoid using any and instead use runtime checks to narrow down the type of your data.

Using Module Augmentation for Global JSON

If you frequently import the same JSON data all throughout your application, module augmentation might be a convenient approach:

// Global typings file (e.g., global.d.ts)
declare module "*.json" {
  const value: any;
  export default value;
}

// Import JSON file without specifying types each time
import globalData from 'path_to_json/globals.json' assert {type: 'json'};

Module augmentation allows you to declare a default module structure for files ending with .json.

Advanced Usage: Converting to a Class

If your project requires you to encapsulate JSON data within a class, TypeScript allows you to define a class that mirrors the structure:

// Defining a class to represent the JSON structure
class MyDataClass {
  id: number;
  name: string;

  constructor(data: any) {
    if (data) {
      this.id = data.id;
      this.name = data.name;
    }
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

// Using the class to wrap JSON data
import jsonData from './data.json' assert {type: 'json'};

const myDataInstance = new MyDataClass(jsonData);
myDataInstance.greet();

The class constructor can be designed to take a JSON object and map the data to class properties.

Combining JSON and TypeScript for Configuration Files

JSON files are commonly used for configuration. We can leverage TypeScript to ensure these configurations adhere to a strict schema:

// Config interface
define an interface for the.config.json';

// Typing the config JSON
import appConfig from './config.json' assert {type: 'json'} as AppConfig;

// Now, appConfig will have the correct type and our application can use it shot;.json "could not be found" errors.


Working With TypeScript and JSON in Node.js

In a Node.js context, you may also use require to import your JSON files:

// Using require instead of ES6 import
const myData = require('./data.json') assert {type: 'json'};
console.log(myData);

Using require can be beneficial when you don’t wish to use TypeScript’s esoteric synchronization module structures.

Conclusion

In conclusion, importing JSON files in TypeScript is a straightforward process that becomes even more powerful with type assertions. Ensuring your tsconfig.json is properly configured is the first crucial step. After that, TypeScript’s typing system provides numerous ways to interact safely and efficiently with JSON data, from basic imports to complex data handling patterns. Be sure to use the power of types to ensure your data structures are predictable and to prevent runtime errors.