How to Import JSON Files in TypeScript (resolveJsonModule & More)

You import JSON files in TypeScript with a normal import statement once resolveJsonModule is on in your tsconfig. TypeScript then reads the file and infers a type for every property:

import config from "./store-config.json";
console.log(config.storeName);

I tested every example here in strict mode with TypeScript 7.0.2 and Node.js v22.22.2, and each output below is copied from my console.

We’ll cover the tsconfig settings, the TS2732 error, typing the data, ESM import attributes, require and reading JSON at runtime.

Import a JSON file with resolveJsonModule

Here’s the sample file every example reads, a small store config saved as store-config.json:

{
  "storeName": "Cascade Outfitters",
  "city": "Seattle",
  "state": "WA",
  "currency": "USD",
  "freeShippingMin": 49.99,
  "openedOn": "2026-03-02",
  "featured": ["Trail Jacket", "Camp Mug", "Rain Shell"]
}

Turn on resolveJsonModule in tsconfig.json (I pass the same options as tsc flags):

{
  "compilerOptions": {
    "module": "commonjs",
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}
import config from "./store-config.json";

console.log(`${config.storeName} (${config.city}, ${config.state})`);
console.log(`Free shipping over $${config.freeShippingMin.toFixed(2)}`);
console.log("Featured:", config.featured.join(", "));

Output:

Cascade Outfitters (Seattle, WA)
Free shipping over $49.99
Featured: Trail Jacket, Camp Mug, Rain Shell
Command Prompt output of tsc and node importing store-config.json in TypeScript with resolveJsonModule
The compiled script reads the JSON file and prints the store name, the shipping minimum and the featured list.

Keep the ./ and the .json extension in the path. If you’d rather turn the data into a list, see converting JSON to an array in TypeScript.

Why does TypeScript say “Cannot find module ‘./file.json'”?

That’s error TS2732, and it means resolveJsonModule is off. TypeScript 7 already resolved my import with its default settings, so I switched the option off to reproduce what older tsconfig files show:

import config from "./store-config.json";

console.log(`${config.storeName} (${config.city}, ${config.state})`);
console.log(`Free shipping over $${config.freeShippingMin.toFixed(2)}`);
console.log("Featured:", config.featured.join(", "));

Compiler output:

json_off.ts(1,20): error TS2732: Cannot find module './store-config.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.
Command Prompt output of TypeScript error TS2732 Cannot find module store-config.json Consider using resolveJsonModule
The compiler names the fix itself: enable --resolveJsonModule.

Set "resolveJsonModule": true and the error is gone. If it still fails, check the path and that the file sits inside rootDir; fixing Cannot find module in TypeScript walks through the other causes.

How TypeScript types imported JSON

You don’t write an interface for an imported file. TypeScript reads the JSON and infers string, number and string[], which typeof config turns into a reusable type:

import config from "./store-config.json";

type StoreConfig = typeof config;

function qualifies(orderTotal: number, store: StoreConfig): boolean {
  return orderTotal >= store.freeShippingMin;
}

console.log("$52.40 order ships free:", qualifies(52.4, config));
console.log("$18.75 order ships free:", qualifies(18.75, config));

const minimum: string = config.freeShippingMin;

Compiler output:

json_typed.ts(12,7): error TS2322: Type 'number' is not assignable to type 'string'.

The last line fails on purpose: the inferred type knows freeShippingMin is a number. Need your own named type instead? Read converting JSON to a TypeScript interface.

Import JSON in ES modules with with { type: “json” }

Node.js loads JSON into an ES module only with the type: "json" attribute. With module set to nodenext, an .mts file without it fails with TS1543. Add it to static imports and to the options of a dynamic import():

import config from "./store-config.json" with { type: "json" };

console.log("Static import:", config.storeName, "since", config.openedOn);

const { default: lazy } = await import("./store-config.json", { with: { type: "json" } });
console.log("Dynamic import:", lazy.featured.length, "featured items");

Output:

Static import: Cascade Outfitters since 2026-03-02
Dynamic import: 3 featured items
Command Prompt output of a TypeScript .mts file importing JSON with import attributes with type json, compiled with module nodenext and run in Node.js
Both the static import and the dynamic import() load the same JSON file in Node.js.

Import attributes need module set to esnext, nodenext or preserve (tsc reports TS2823 otherwise). Older tutorials show assert; use with. For config values that differ per machine, see environment variables in TypeScript.

Load JSON with require in CommonJS

In a CommonJS project, import ... = require() keeps the inferred types. A bare const x = require() needs @types/node and gives you any:

import config = require("./store-config.json");

console.log(config.storeName, "uses", config.currency);

Output:

Cascade Outfitters uses USD

Skip as casts on that any value; they hide mistakes. Type casting in TypeScript explains when a cast is safe.

Read a JSON file at runtime with fs and JSON.parse

Imports are fixed at build time, so read files that change with fs. JSON.parse() returns any, so I store it as unknown and check it with a type guard, as covered in TypeScript type narrowing:

import { readFileSync } from "node:fs";
import { join } from "node:path";

interface StoreConfig {
  storeName: string;
  freeShippingMin: number;
  featured: string[];
}

function isStoreConfig(value: unknown): value is StoreConfig {
  const v = value as StoreConfig;
  return typeof v?.storeName === "string" && typeof v.freeShippingMin === "number"
    && Array.isArray(v.featured);
}

const raw: unknown = JSON.parse(readFileSync(join(__dirname, "store-config.json"), "utf8"));

if (isStoreConfig(raw)) {
  console.log(`${raw.storeName}: free shipping over $${raw.freeShippingMin.toFixed(2)}`);
} else {
  console.log("store-config.json has the wrong shape");
}

Output:

Cascade Outfitters: free shipping over $49.99
Command Prompt output of TypeScript reading store-config.json with readFileSync and JSON.parse, checked by a type guard
The guard confirms the shape before the code touches freeShippingMin.

TypeScript 7 doesn’t load @types packages automatically, so I installed @types/node and passed --types node. In a tsconfig, that’s "types": ["node"].

Which way to import JSON files in TypeScript should you use?

MethodBest forTyped?
import + resolveJsonModuleBundlers and CommonJS projectsYes, inferred
import ... with { type: "json" }ES modules running in Node.jsYes, inferred
import x = require()Older CommonJS codeYes, inferred
fs.readFileSync + JSON.parseFiles that change at runtimeNo, use a guard

These related TypeScript tutorials pick up where this one stops:

Frequently asked questions

How do I import a JSON file in TypeScript?

Set "resolveJsonModule": true in tsconfig.json, then write import data from "./data.json". In Node.js ES modules, add with { type: "json" }.

Why do I get error TS2732?

TS2732 means TypeScript can’t resolve a .json import because resolveJsonModule is off. Turn it on and check the relative path.

Do I need an interface for imported JSON?

No. TypeScript infers the type from the file. Use typeof data to reuse it, or write an interface when the JSON is read at runtime.

Should I use assert or with for JSON imports?

Use with { type: "json" }. The assert keyword is the older proposal syntax.

Can I import JSON without resolveJsonModule?

Yes, read it at runtime with fs.readFileSync and JSON.parse, then validate the result with a type guard.

Where is resolveJsonModule documented?

See resolveJsonModule in the official TypeScript tsconfig reference.