Skip to content

Importing arrays from JSON results in incorrect type checking #34997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dmaretskyi opened this issue Nov 8, 2019 · 4 comments · Fixed by #35048
Closed

Importing arrays from JSON results in incorrect type checking #34997

dmaretskyi opened this issue Nov 8, 2019 · 4 comments · Fixed by #35048
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@dmaretskyi
Copy link

dmaretskyi commented Nov 8, 2019

TypeScript Version: 3.8.0-dev.20191105, 3.7.2

Search Terms: JSON incorrect type checking

Code

import data from "./data.json";

interface Foo {
  str: string;
}

const a: Foo[] = data.foo; // no error
const b: Foo[] = data.foo; // compilation error

interface Bar {
  bool: string;
}

const c: Bar[] = data.foo; // no error (even though the types don't match)
const d: Bar[] = data.foo; // compilation error

data.json:

{
  "foo": [
    {
      "bool": true,
      "str": "123"
    }
  ]
}

Expected behavior:

Both assignments to a and b shouldn't error. Assignments to c and d should both error.

Actual behavior:

It seems like the first assignment per type is always treated correctly by tsc while the latter ones are all compilation errors. This happens regardless whether the types actually match or not.

Removing the lines with errors results in successfull compilation even though the types don't match.

Repo with example: https://github.com/Marik-D/typescipt-issue

tsc output:

index.ts:8:7 - error TS2322: Type '{ bool: boolean; str: string; }[]' is not assignable to type 'Foo[]'.

8 const b: Foo[] = data.foo;
        ~

index.ts:15:7 - error TS2322: Type '{ bool: boolean; str: string; }[]' is not assignable to type 'Bar[]'.

15 const d: Bar[] = data.foo;
         ~

tsconfig:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "strict": true,
    "outDir": "dist"
  }
}
@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Nov 8, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.8.0 milestone Nov 8, 2019
@RyanCavanaugh
Copy link
Member

This is such a weird bug I literally didn't believe the report wasn't missing a typo.

Repros starting at 3.6; can happen with any assignability check that happens twice

import data from "./data.json";

interface Foo {
  str: string;
}

fn(data.foo);
fn(data.foo); // <-- error

function fn(arg: Foo[]) { }

Totally bananas that we haven't gotten another report of this yet.

@weswigham
Copy link
Member

weswigham commented Nov 8, 2019

So, two things going wrong here. 1. We actually attempt to issue an error on both calls, but for the first, we refine the error location to a property in the json document (because we use fresh literal properties to refine error locations), then toss out the error because it's not for the right file.
2. There error is there at all because the array literal is preventing unfreshness from being propagated through it - so the outer object is unfreshened, but the array and its member objects are not.

@fatcerberus
Copy link

It considers the JSON import to be a fresh object literal? Huh. That’s a bit surprising.

@weswigham
Copy link
Member

It considers the JSON import to be a fresh object literal?

No, it's very explicitly unfreshed - but that unfreshing is mistakenly prevented from propagating down into the nested object within the array literal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
4 participants