Skip to content

[Feature] Use JSON Schema to determine imported JSON type when availableΒ #49314

@Jamesernator

Description

@Jamesernator

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:

Screenshot from 2022-05-31 06-42-18

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Out of ScopeThis idea sits outside of the TypeScript language design constraintsSuggestionAn idea for TypeScript

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions