Reputation: 10577
I have a JSON
file that looks like following:
{
"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'm trying to import it into a .tsx
file. For this I added this to the type definition:
declare module "*.json" {
const value: any;
export default value;
}
And I'm importing it like this.
import colors = require('../colors.json')
And in the file, I use the color primaryMain
as colors.primaryMain
. However I get an error:
Property 'primaryMain' does not exist on type 'typeof "*.json"
Upvotes: 513
Views: 801773
Reputation: 467
import data from '../../data/data.json;
is also an option.
Upvotes: 0
Reputation: 1538
I tried all suggestions in this thread to-date, including setting resolveJsonModule to true, moduleResolution to "node", and various formats of the include statement (assert/with) and require. I also closed and restarted VSCode between most changes. Nothing here worked.
But from my ./src/index.ts, I did get import metadata from './block.json
working and with no other errors, by setting the tsconfig.json include
parameter to ["src"]
, and setting "files":["src/block.json"]
. Note that the JSON file is not in the rootDir.
Interestingly (to me anyway) even when the './block.json' was getting the red squigglies, Intellisense on 'metadata' showed all of the properties defined in the JSON. I do not have a declaration of the schema in this project. So VSCode recognized the file and processed its contents even though TS flagged the error.
I don't know if this is version-specific. In this project I have TypeScript 5.3.3, @types/node 20.11.24, and the tsconfig.json below. From rootDir, my src folder has all source, processed by WebPack into ./build. (The reference to ./dist is there in case TypeScript needs a different outDir than WebPack. I can't say this is THE solution for anyone else, or that other solutions might be more elegant for my own purposes or others, only that this configuration absolutely works as A solution for me at this moment.
{
"compilerOptions": {
"composite": true,
"target": "ES2022",
"lib": ["ES2022", "ES2022.String", "DOM", "DOM.Iterable"],
"jsx": "react-jsx",
"useDefineForClassFields": true,
"module": "ES2022",
"moduleResolution": "bundler",
"types": ["node"],
"resolveJsonModule": true,
"allowJs": true,
"checkJs": true,
"outDir": "./dist",
"preserveConstEnums": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": false,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"useUnknownInCatchVariables": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"skipLibCheck": true
},
"include": ["src"],
"files": ["src/block.json"]
}
Upvotes: 0
Reputation: 9350
TypeScript 5.3 introduced Import Attributes, formerly known as Import Assertions, which can provide information about the expected format of an imported module at runtime.
Import Attributes ensure that a module is imported with the correct format. That means a .json
file that actually contains runnable JavaScript code is definitely being interpreted as JSON.
import colors from "./colors.json" with { type: "json" };
Upvotes: 9
Reputation: 2844
You can import a JSON file without modifying tsconfig by specifying explicitly that you are importing JSON
import mydata from './mydataonfile.json' assert { type: "json" };
I know this does not fully answer the question but many people come here to know how to load JSON directly from a file.
Upvotes: 10
Reputation: 1001
In my case I needed to change tsconfig.node.json:
{
"compilerOptions": {
...
"resolveJsonModule": true
},
"include": [..., "colors.json"]
}
And to import like that:
import * as colors from './colors.json'
Or like that:
import colors from './colors.json'
with "esModuleInterop": true
Upvotes: 40
Reputation: 356
In an Angular (typescript) app, I needed to include a .json
file in my environment.ts
. To do so, I had to set two options in tsconfig:
{
"compilerOptions": {
"moduleResolution": "node",
"resolveJsonModule": true
}
}
Then, I could import my json file into the environment.ts
:
import { default as someObjectName } from "../some-json-file.json";
Upvotes: 14
Reputation: 5284
in my case I had to change: "include": ["src"]
to "include": ["."]
in addition to "resolveJsonModule":true
because I tried to import manifest.json
from the root of the project and not from ./src
Upvotes: 0
Reputation: 1143
Here's how to import a json file at runtime
import fs from 'fs'
var dataArray = JSON.parse(fs.readFileSync('data.json', 'utf-8'))
This way you avoid issues with tsc slowing down or running out of memory when importing large files, which can happen when using resolveJsonModule.
Upvotes: 42
Reputation: 18544
With TypeScript 2.9.+ you can simply import JSON files with benefits like typesafety and intellisense by doing this:
import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes"
console.log(colorsJson.primaryBright);
Make sure to add these settings in the compilerOptions
section of your tsconfig.json
(documentation):
"resolveJsonModule": true,
"esModuleInterop": true,
Side notes:
import * as colorsJson from '../colors.json'
Upvotes: 879
Reputation: 91
Note that if you using @kentor ways
Make sure to add these settings in the compilerOptions section of your tsconfig.json (documentation):
You need to add --resolveJsonModule
and--esModuleInterop
behind tsc
command to compile your TypeScript file.
Example:
tsc --resolveJsonModule --esModuleInterop main.ts
Upvotes: 0
Reputation: 377
You should add
"resolveJsonModule": true
as part of compilerOptions to tsconfig.json.
Upvotes: 10
Reputation: 89
Enable "resolveJsonModule": true
in tsconfig.json
file and implement as below code, it's work for me:
const config = require('./config.json');
Upvotes: 0
Reputation: 31873
The import form and the module declaration need to agree about the shape of the module, about what it exports.
When you write (a suboptimal practice for importing JSON since TypeScript 2.9 when targeting compatible module formatssee note)
declare module "*.json" {
const value: any;
export default value;
}
You are stating that all modules that have a specifier ending in .json
have a single export named default
.
There are several ways you can correctly consume such a module including
import a from "a.json";
a.primaryMain
and
import * as a from "a.json";
a.default.primaryMain
and
import {default as a} from "a.json";
a.primaryMain
and
import a = require("a.json");
a.default.primaryMain
The first form is the best and the syntactic sugar it leverages is the very reason JavaScript has default
exports.
However I mentioned the other forms to give you a hint about what's going wrong. Pay special attention to the last one. require
gives you an object representing the module itself and not its exported bindings.
So why the error? Because you wrote
import a = require("a.json");
a.primaryMain
And yet there is no export named primaryMain
declared by your "*.json"
.
All of this assumes that your module loader is providing the JSON as the default
export as suggested by your original declaration.
Note: Since TypeScript 2.9, you can use the --resolveJsonModule
compiler flag to have TypeScript analyze imported .json
files and provide correct information regarding their shape obviating the need for a wildcard module declaration and validating the presence of the file. This is not supported for certain target module formats.
Upvotes: 221
Reputation: 720
Often in Node.js applications a .json is needed. With TypeScript 2.9, --resolveJsonModule allows for importing, extracting types from and generating .json files.
Example #
// tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"resolveJsonModule": true,
"esModuleInterop": true
}
}
// .ts
import settings from "./settings.json";
settings.debug === true; // OK
settings.dry === 2; // Error: Operator '===' cannot be applied boolean and number
// settings.json
{
"repo": "TypeScript",
"dry": false,
"debug": false
}
Upvotes: 10
Reputation: 3901
Another way to go
const data: {[key: string]: any} = require('./data.json');
This was you still can define json type is you want and don't have to use wildcard.
For example, custom type json.
interface User {
firstName: string;
lastName: string;
birthday: Date;
}
const user: User = require('./user.json');
Upvotes: 7
Reputation: 6023
It's easy to use typescript version 2.9+. So you can easily import JSON files as @kentor decribed.
But if you need to use older versions:
You can access JSON files in more TypeScript way. First, make sure your new typings.d.ts
location is the same as with the include
property in your tsconfig.json
file.
If you don't have an include property in your tsconfig.json
file. Then your folder structure should be like that:
- app.ts
+ node_modules/
- package.json
- tsconfig.json
- typings.d.ts
But if you have an include
property in your tsconfig.json
:
{
"compilerOptions": {
},
"exclude" : [
"node_modules",
"**/*spec.ts"
], "include" : [
"src/**/*"
]
}
Then your typings.d.ts
should be in the src
directory as described in include
property
+ node_modules/
- package.json
- tsconfig.json
- src/
- app.ts
- typings.d.ts
As In many of the response, You can define a global declaration for all your JSON files.
declare module '*.json' {
const value: any;
export default value;
}
but I prefer a more typed version of this. For instance, let's say you have configuration file config.json
like that:
{
"address": "127.0.0.1",
"port" : 8080
}
Then we can declare a specific type for it:
declare module 'config.json' {
export const address: string;
export const port: number;
}
It's easy to import in your typescript files:
import * as Config from 'config.json';
export class SomeClass {
public someMethod: void {
console.log(Config.address);
console.log(Config.port);
}
}
But in compilation phase, you should copy JSON files to your dist folder manually. I just add a script property to my package.json
configuration:
{
"name" : "some project",
"scripts": {
"build": "rm -rf dist && tsc && cp src/config.json dist/"
}
}
Upvotes: 19