Question
I have a JSON file like this:
{
"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 want to import this JSON into a .tsx file. I added this module declaration:
declare module "*.json" {
const value: any;
export default value;
}
Then I imported it like this:
import colors = require('../colors.json')
In the file, I try to access a property such as colors.primaryMain, but I get this error:
Property 'primaryMain' does not exist on type 'typeof "*.json"'
How should JSON files be imported correctly in TypeScript so that their properties can be accessed without this error?
Short Answer
By the end of this page, you will understand how JSON imports work in TypeScript, why require and export default can conflict, and how to correctly import JSON in a .ts or .tsx file. You will also learn how to configure TypeScript for JSON modules and how to make imported JSON safer with types.
Concept
TypeScript can import JSON files, but the import style must match how the JSON module is declared and how the compiler is configured.
In this question, the key issue is a mismatch:
- The declaration says JSON files have a default export.
- The code uses
require(...)-style import syntax.
Those two patterns are different module systems.
Why this matters
In real projects, configuration, theme values, translations, mock data, and metadata are often stored in JSON files. If TypeScript does not understand the shape of the imported file, you may get errors when reading properties such as colors.primaryMain.
The core idea
There are two common ways TypeScript handles JSON:
-
Modern TypeScript configuration using
resolveJsonModule- TypeScript reads the JSON file directly.
- You can import it with standard ES module syntax.
-
Manual module declaration such as
declare module "*.json"- You tell TypeScript what a JSON import looks like.
- Your import syntax must match that declaration.
If your declaration exports default, then your import should be:
import colors from ;
Mental Model
Think of a JSON file as a box of labeled values.
Your colors.json box contains labels like:
primaryMainsecondaryMaindarkGrey
Importing the JSON file is like bringing that box into your code.
But TypeScript also wants a label for the box itself: how is this box exported?
- If you say, "this box is exported as the default item," then you must pick it up with a default import.
- If you try to pick it up with a different system, TypeScript may not understand what is inside the box.
So the problem is not the JSON data itself. The problem is that the way you declared the box and the way you imported the box do not match.
Syntax and Examples
Recommended syntax with resolveJsonModule
In tsconfig.json:
{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true
}
}
Then import the JSON like this:
import colors from '../colors.json';
console.log(colors.primaryMain);
This is the simplest and most common approach.
Using a manual declaration
If you use this declaration:
declare module "*.json" {
const value: any;
export default value;
}
Step by Step Execution
Consider this code:
import colors from '../colors.json';
const main = colors.primaryMain;
console.log(main);
Here is what happens step by step:
- TypeScript sees
import colors from '../colors.json'. - If
resolveJsonModuleis enabled, TypeScript reads the JSON file and treats it like a module. - The imported object is assigned to the local variable
colors. colors.primaryMainlooks up theprimaryMainproperty inside the imported object.- The value
"#05B4F0"is assigned tomain. console.log(main)prints the color value.
With your original code:
import colors = require('../colors.json');
TypeScript uses a different module interpretation. Since your declaration described a default export, TypeScript does not connect that cleanly with the require import assignment, so property access can fail at the type level.
Real World Use Cases
JSON imports are used in many practical situations:
Theme configuration
import colors from './colors.json';
const buttonStyle = {
backgroundColor: colors.primaryMain,
color: '#fff'
};
App settings
import settings from './settings.json';
if (settings.enableLogging) {
console.log('Logging is on');
}
Translation files
import en from './locales/en.json';
console.log(en.welcomeMessage);
Mock API data for development
import users from './mock-users.json';
console.log(users.length);
Real Codebase Usage
In real codebases, developers usually use JSON imports in a few common patterns.
Configuration objects
JSON is often imported once and reused throughout the app:
import colors from './colors.json';
export const theme = {
primary: colors.primaryMain,
secondary: colors.secondaryMain
};
Validation after import
If JSON comes from a file that may change, teams often validate it:
import rawConfig from './config.json';
function hasApiUrl(value: any): value is { apiUrl: string } {
return value && typeof value.apiUrl === 'string';
}
if (!hasApiUrl(rawConfig)) {
throw new Error('Invalid config.json');
}
Mapping imported JSON into app-specific structures
Common Mistakes
1. Mixing default exports with require
Broken example:
declare module "*.json" {
const value: any;
export default value;
}
import colors = require('../colors.json');
console.log(colors.primaryMain);
Why it fails:
- The declaration says
default export - The import uses
requiresyntax
Fix:
import colors from '../colors.json';
2. Forgetting resolveJsonModule
Broken setup:
{
"compilerOptions": {
"strict":
Comparisons
| Approach | Example | When to use | Notes |
|---|---|---|---|
| Default JSON import | import colors from '../colors.json' | Best for most modern TypeScript projects | Works well with resolveJsonModule |
| Require import | const colors = require('../colors.json') | Older CommonJS codebases | Less common in modern TS/React code |
| Import assignment | import colors = require('../colors.json') | Mostly older TypeScript/CommonJS setups | Can conflict with export default declarations |
| Manual module declaration | declare module '*.json' | When TypeScript needs help understanding JSON modules |
Cheat Sheet
Correct import for JSON with default export
import colors from '../colors.json';
Matching declaration
declare module "*.json" {
const value: any;
export default value;
}
Recommended tsconfig.json
{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true
}
}
Accessing properties
console.log(colors.primaryMain);
Avoid this mismatch
FAQ
How do I import a JSON file in TypeScript?
Usually like this:
import data from './file.json';
This works best with resolveJsonModule enabled.
Why does TypeScript say a property does not exist on my JSON import?
This often happens because the import syntax does not match the module declaration, or TypeScript is not configured to resolve JSON modules properly.
Do I still need declare module "*.json"?
Often no. In many modern TypeScript projects, resolveJsonModule is enough.
Should I use require to import JSON in TypeScript?
Only in older CommonJS-style codebases. In modern TypeScript and React code, import ... from is usually better.
What does resolveJsonModule do?
It tells TypeScript to treat .json files as modules that can be imported.
Is using any for imported JSON a good idea?
It is convenient, but not ideal. It removes type safety. A typed object or inferred type is safer.
Can I import JSON in a file?
Mini Project
Description
Build a small theme configuration module that imports a JSON color palette and uses it in TypeScript. This demonstrates correct JSON importing, property access, and optional type checking in a practical UI-style setup.
Goal
Import a JSON palette into TypeScript and expose a typed theme object that uses values such as primaryMain and darkGrey.
Requirements
- Create a
colors.jsonfile with color values. - Import the JSON file into a TypeScript file using the correct syntax.
- Build and export a
themeobject using values from the JSON. - Log at least two theme values to confirm the import works.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular Dependency Injection: Fix "Can't Resolve All Parameters for Component" Errors
Learn why Angular shows "Can't resolve all parameters for component" and how to fix service injection issues in components.