How to Import JSON Files in TypeScript?

Recently, I was working on a TypeScript project where I needed to import and use data from a JSON file. There are actually several approaches to handling JSON imports in TypeScript, each with its own advantages.

In this tutorial, I’ll guide you through the various methods for importing JSON files in TypeScript, discuss type safety considerations, and demonstrate how to overcome common challenges. So let’s dive in!

Understanding JSON Imports in TypeScript

TypeScript doesn’t natively know how to handle JSON files. By default, when you try to import a JSON file, TypeScript will give you an error like:

Cannot find module './data.json' or its corresponding type declarations.

This is because TypeScript needs to be configured to recognize and handle JSON imports properly. Fortunately, there are several ways to solve this.

Sample JSON File

Throughout this article, I’ll refer to the following sample JSON file (data.json):

{
  "users": [
    {
      "id": 1,
      "firstName": "John",
      "lastName": "Smith",
      "email": "john.smith@example.com",
      "isActive": true,
      "address": {
        "street": "123 Main St",
        "city": "Boston",
        "state": "MA",
        "zipCode": "02108"
      },
      "tags": ["premium", "verified"]
    },
    {
      "id": 2,
      "firstName": "Sarah",
      "lastName": "Johnson",
      "email": "sarah.j@example.com",
      "isActive": false,
      "address": {
        "street": "456 Oak Ave",
        "city": "San Francisco",
        "state": "CA",
        "zipCode": "94103"
      },
      "tags": ["trial"]
    }
  ],
  "config": {
    "apiVersion": "1.0.0",
    "environment": "development",
    "features": {
      "darkMode": true,
      "notifications": false
    }
  }
}

This JSON file contains user data and application configuration that we’ll work with in our examples.

Check out TypeScript Check If String Is Number

Method 1: Enable resolveJsonModule in tsconfig.json

The simplest way to import JSON files in TypeScript is by enabling the resolveJsonModule option in your TypeScript configuration file.

Here are the steps to import JSON files using this method:

  1. Open your tsconfig.json file
  2. Add or set resolveJsonModule to true in the compilerOptions section
  3. Make sure esModuleInterop is also set to true

Your tsconfig.json should look something like this:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    // other options...
  }
}

Once you’ve updated your configuration, you can import JSON files directly:

import data from './data.json';

// You can now use the data
console.log(data.firstName); // Assuming data has a firstName property

This approach is clean and straightforward. TypeScript will automatically infer the types from your JSON structure, giving you type checking and autocompletion.

Read Convert TypeScript Enums to Arrays

Method 2: Using require() with Type Assertions

If you’re working in a Node.js environment or can’t modify your tsconfig, you can use the require() function with type assertions:

// Define an interface that matches your JSON structure
interface User {
  id: number;
  firstName: string;
  lastName: string;
  email: string;
}

// Use require with type assertion
const userData = require('./user-data.json') as User[];

// Now you can safely use the data with type checking
console.log(userData[0].firstName);

The downside of this approach is that you need to manually define the types that match your JSON structure, which can be tedious for complex JSON files.

Check out How to Use Array.find() in TypeScript?

Method 3: Using the fs Module to Read JSON Files

For more control over when and how the JSON is loaded, you can use the Node.js file system module:

import * as fs from 'fs';
import * as path from 'path';

interface Config {
  apiKey: string;
  endpoint: string;
  timeout: number;
}

function loadConfig(): Config {
  const filePath = path.resolve(__dirname, './config.json');
  const fileContent = fs.readFileSync(filePath, 'utf-8');
  return JSON.parse(fileContent) as Config;
}

const config = loadConfig();
console.log(`API Key: ${config.apiKey}, Endpoint: ${config.endpoint}`);

This approach gives you more flexibility, such as error handling, dynamic file paths, and loading JSON files conditionally.

Check out How to Iterate Over Enums in TypeScript?

Method 4: Using import() with Type Assertions

If you’re using a module bundler like webpack, you can use the dynamic import() function:

interface AppSettings {
  theme: string;
  notifications: boolean;
  language: string;
}

async function loadSettings(): Promise<AppSettings> {
  const settings = await import('./settings.json');
  return settings.default as AppSettings;
}

// Usage in async context
async function initApp() {
  const settings = await loadSettings();
  console.log(`Theme: ${settings.theme}, Language: ${settings.language}`);
}

initApp();

This method is useful when you need to load JSON files dynamically based on runtime conditions.

Add Type Definitions for JSON Files

For better type safety, you can create type definitions for your JSON files. Here’s how:

  1. Create a types.d.ts file in your project
  2. Add module declarations for your JSON files
// types.d.ts
declare module "*.json" {
  const value: any;
  export default value;
}

For more specific typing, you can declare types for individual files:

// types.d.ts
declare module "./user-data.json" {
  export interface User {
    id: number;
    firstName: string;
    lastName: string;
    email: string;
  }
  const value: User[];
  export default value;
}

Working with Dynamic JSON Properties

Sometimes, your JSON might have dynamic keys or complex structures. Here’s how to handle them:

// For a JSON with dynamic keys
interface DynamicData {
  [key: string]: {
    value: number;
    label: string;
  }
}

import stateData from './us-states.json';

// Using the data
const californiaInfo = (stateData as DynamicData)['California'];
console.log(`${californiaInfo.label}: ${californiaInfo.value}`);

Check out TypeScript Promise

Real-World Example: Working with US State Data

Let’s look at a practical example using US state data:

// us-states.json
{
  "AL": {
    "name": "Alabama",
    "capital": "Montgomery",
    "population": 4903185
  },
  "AK": {
    "name": "Alaska",
    "capital": "Juneau",
    "population": 731545
  },
  // ...other states
}

Now let’s import and use this data:

// Enable resolveJsonModule in tsconfig.json first

// Define the types
interface StateInfo {
  name: string;
  capital: string;
  population: number;
}

interface States {
  [stateCode: string]: StateInfo;
}

// Import the JSON
import statesData from './us-states.json';

// Type assertion
const states = statesData as States;

// Use the data
function getStateCapital(stateCode: string): string | undefined {
  return states[stateCode]?.capital;
}

function getPopulationByState(stateName: string): number | undefined {
  const stateEntry = Object.entries(states).find(
    ([_, info]) => info.name === stateName
  );
  return stateEntry?.[1].population;
}

// Example usage
console.log(`The capital of California is ${getStateCapital('CA')}`);
console.log(`Florida has a population of ${getPopulationByState('Florida')}`);

Troubleshooting Common Issues

Here are some common issues that you might face and fixes.

Issue 1: Module not found errors

If you’re still getting “Cannot find module” errors despite enabling resolveJsonModule, try these fixes:

  1. Make sure your TypeScript version is 2.9.0 or higher
  2. Verify that both resolveJsonModule and esModuleInterop are set to true
  3. Check the file path is correct (case-sensitive!)
  4. Restart your TypeScript server (in VS Code: Ctrl+Shift+P → “TypeScript: Restart TS Server”)

Issue 2: Type errors when accessing properties

If TypeScript doesn’t recognize properties in your JSON:

// Add a type assertion when importing
import rawData from './data.json';
interface MyData {
  user: {
    name: string;
    age: number;
  }
}

const data = rawData as MyData;
console.log(data.user.name); // Now TypeScript knows this exists

In this tutorial, I explained how to import JSON files in TypeScript using different methods. I hope you found this article helpful.

You may also like:

Power Apps functions free pdf

30 Power Apps Functions

This free guide walks you through the 30 most-used Power Apps functions with real business examples, exact syntax, and results you can see.

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App