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:
- Typescript 2.9.0 has a bug with this JSON feature, it was fixed with 2.9.2
- The esModuleInterop is only necessary for the default import of the colorsJson. If you leave it set to false then you have to import it with
import * as colorsJson from '../colors.json'
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:
- Typescript 2.9.0 has a bug with this JSON feature, it was fixed with 2.9.2
- The esModuleInterop is only necessary for the default import of the colorsJson. If you leave it set to false then you have to import it with
import * as colorsJson from '../colors.json'
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.
New to TS, struggling with types of JSON module import.
Need to read through a JSON file
Is there a way to import the type of a json file without importing the json file? (typescript, vite)
How to force a type when importing a JSON file?
Videos
Hi everyone, I'm new to TypeScript and currently I'm stuck with a problem for which I haven't found many resources on the internet, so I thought I could as you for some help.
Let me give you some context. I have a JSON file with the following content:
{
"first": {
"name": "FirstName",
"age": 21
},
"second": {
"name": "SecondName",
"random": false
}
}My idea is that this files serves as some kind of hashmap, so I'm able to do something like this:
import data from 'test.json';
const access = (key: string) => {
const value = data[key];
const name = value?.name;
const age = value?.age;
const random = value?.random;
};Ideally, this would mean that my JSON get's typed as something like:
type TypeIWant = {
[key: string]: ValuesTypeIWant;
};
type ValuesTypeIWant = {
name: string;
age?: number;
random?: boolean;
};However, TypeScript gives me this type instead:
type TypeIGet = {
first: {
name: string;
age: number;
};
second: {
name: string;
random: boolean;
};
};I undestand why TS it's giving me that type, but I want to use the values in the JSON file in dynamic routing, so I need to be able to do something like values[anyString], even if that returns me null, but I always get to an error similar to this one:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ first: { name: string; age: number; }; second: { name: string; random: boolean; }; }'.The compiler doesn't even allow me to type cast it to TypeIWant. I've also tried creating a Map from those values, but still it doesn't work.
What can be done in this situation? Is there some way of telling the compiler that imported JSON data satisfied certain interface or type? Or is there a way to abstract the literal type that TS is generating from the JSON values to make it more generic, etc?
Considerations: I'm using the resolveJsonModule flag in my tsconfig and also, this is a simplified example, the full JSON has more than two keys, but the idea is the same, all keys have the same schema (if some keys are considered as optional).
» npm install json-server