Skip to content

JSON Module Type Resolution With Heterogeneous Arrays #37831

Closed
@jcgsville

Description

@jcgsville

TypeScript Version: 3.9.0-dev.20200407

Search Terms:
json module array type resolveJsonModule

Code

schema1.json

[
  {
    "foo": 1,
    "bar": 2
  },
  {
    "baz": "something"
  }
]

schema2.json

[
  1,
  "foo"
]
import schema1 from './schema1.json';
import schema2 from './schema2.json';
const example1: [ { foo: number; bar: number }, { baz: string; } ] = schema1;
const example2: [ number, string ] = schema2;

Expected behavior:
I would expect this to compile correctly.

Actual behavior:
There are two compile errors on assignment.

Type '({ foo: number; bar: number; baz?: undefined; } | { baz: string; foo?: undefined; bar?: undefined; })[]' is missing the following properties from type '[{ foo: number; bar: number; }, { baz: string; }]': 0, 1

and

Type '(string | number)[]' is missing the following properties from type '[number, string]': 0, 1

Playground Link:
Because this relies on the resolveJsonModule flag, I cannot reproduce this in a typescript playground. Instead, I have created this small repository which demonstrates the failed compilation.
https://github.com/jcgsville/typescript-json-bug-repro

Related Issues:
Here is a similar issue, but doesn't address how it infers the type of arrays.
#27913

Discussion:
I could see an argument that this is intended behavior and a known limitation of the degree of sophistication of a type inferred from JSON. However, I'd expect that the JSON module resolution would resolve it to a more strict type, and the user of the module could loosen it on assignment/usage if they want.

For example, if the type of schema1 was resolved to be [ { foo: number; bar: number }, { baz: string } ], then assigning it to a looser type would succeed. See the following example

const schema3: [ { foo: number; bar: number }, { baz: string; } ] = [
  {
    foo: 1,
    bar: 2
  },
  {
    baz: 'something'
  }
];
const example3: ({ foo: number; bar: number; } | { baz: string })[] = schema3;

There are many use cases for heterogeneous arrays, but I encountered this when trying to represent anyOf in JSON Schema in a JSON module in a typescript project, which is currently impossible to do with @types/json-schema without an as unknown cast.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions