Repository navigation
[Feature] Use JSON Schema to determine imported JSON type when availableΒ #49314
Description
Suggestion
π Search Terms
json schema
β Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.
β Suggestion
Currently when importing JSON the types provided is basically just the inferred type treated the JSON as an object literal.
It would however be helpful to support JSON schema declared types to create types that may be either be more narrow or less narrow that more accurately reflect what one can expect with the JSON.
π Motivating Example
Consider as one example the following JSON:
// mime-map.json
{
"mimeTypes": {
"js": "text/javascript",
"mjs": "text/javascript",
"cjs": "application/node",
"json": "application/json"
}
}When we import it, we are unable to use this as a general record object despite that being the intention of the value:
import mimeMap from "./mime-map.json" assert { "type": "json" };
const extension: string = getExtensionSomehow();
// Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ js: string; mjs: string; cjs: string; json: string; }'.
const mimeType = mimeMap.mimeTypes[extension];
if (mimeType === undefined) {
// ...Unrecognized file type
} else {
// ...do something with the type
}This happens because the inferred type is too narrow, now there's no way that TS could know this directly, however JSON schema is an existing mechanism for declaring such types.
For example if I were to define the schema:
// mime-map.schema.json
{
"$schema": "http://json-schema.org/schema",
"type": "object",
"properties": {
"mimeTypes": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}This would effectively declare a JSON object of type:
{
mimeTypes: Record<string, string>
}Existing tooling already has support for such schemas, for example VSCode can already recognize incorrect types in a file which such a schema:
It would be nice if TS could also recognize JSON schema types, and generate appropriate TS types for them so that types when imported correspond more appropriately.
π» Use Cases
The core use case is that JSON types would more accurately represented by TS recognizing a JSON Schemas, this would allow the JSON file to evolve more so with TS still being able to receive correct type information about the contents rather than just a best guess based on the object shapes.
Notes
This is a potentially breaking change for existing JSON imports, however in most cases people would probably want the JSON Schema they are using. If there was significant breakage an opt-in might be neccessary e.g. useJSONSchema in tsconfig or similar.

Activity
[-][Feature] Use JSON schema to determine JSON type when available[/-][+][Feature] Use JSON Schema to determine JSON type when available[/+][-][Feature] Use JSON Schema to determine JSON type when available[/-][+][Feature] Use JSON Schema to determine imported JSON type when available[/+]MartinJohns commentedon May 31, 2022
Related: #32063
Personally I don't really like this suggestion. JSON Schema is just too... weird. And support for it would just be half-baked. Many features can't be represented in TypeScript types (e.g.
oneOfandnot, orpropertyNames.patternandadditionalProperties). With some other features it's fairly unclear how TypeScript should behave, for exampledefault: What type should TypeScript use here? Thedefaultvalue is not inserted in the absence of a value, so having an optional property makes most sense and the type provided for the value indefaultis dropped entirely. Fun fact: The value fordefaultdoes not have to validate against the schema, you can say the property stores astring, but thedefaultis the number123.fatcerberus commentedon May 31, 2022
π±
I'm... quite scared right now.
MartinJohns commentedon May 31, 2022
It's mentioned here: https://json-schema.org/understanding-json-schema/reference/generic.html
That being said, the value in my example would not be
123, but it would still beundefined(as thedefaultis not inserted). But according to JSON Schema thisundefinedshould be treated as if it were the value123.I'd also expect some library / tools to wrongly insert the
defaultvalue in absence of the property.RyanCavanaugh commentedon May 31, 2022
The Venn diagram of things supported by JSON Schema and by TypeScript has substantial area in both non-overlapping regions, including things we're likely to not ever implement (maxProperties, minLength, etc). Without a 1:1 translation between JSON Schema and TS we'd be left making a ton of policy decisions that people might need to be configurable, and it'd just be a huge mess. But this can be done out-of-band by any tool (such tools already exist) according to the particular project's need without any significant damage to the overall scenario.
Jamesernator commentedon Feb 27, 2023
I'm gonna close this in favour of a more direct TypeScript typings oriented approach.