Skip to content
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

ts2322 incorrectly triggered when importing json #58734

Closed
MarByteBeep opened this issue Jun 1, 2024 · 9 comments
Closed

ts2322 incorrectly triggered when importing json #58734

MarByteBeep opened this issue Jun 1, 2024 · 9 comments
Labels
Duplicate An existing issue was already created

Comments

@MarByteBeep
Copy link

MarByteBeep commented Jun 1, 2024

πŸ”Ž Search Terms

ts2322, json, array

πŸ•— Version & Regression Information

  • I was unable to test this on prior versions because I don't expect this has ever worked properly

I did test this on v5.5.0-dev.20240601

⏯ Playground Link

I wasn't able to add an external JSON to the Playground

πŸ’» Code

Create test.json with following content

[
  {
    "field": [1, 200]
  }
]

Now run the following code

import test from './test.json';

type MyType = {
  field: [number, number]
}

const t: MyType[] = test;

πŸ™ Actual behavior

Observe that ts2322 is triggered:

Type '{ field: number[]; }[]' is not assignable to type 'MyType[]'.
  Type '{ field: number[]; }' is not assignable to type 'MyType'.
    Types of property 'field' are incompatible.
      Type 'number[]' is not assignable to type '[number, number]'.
        Target requires 2 element(s) but source may have fewer.

For some reason TS assumes there may be fewer elements, even though the JSON clearly has a single element with an array containing exactly two numbers. When copying the content directly into the ts file, like so:

const t: MyType[] = [
  {
    "field": [1, 200]
  }
];

no such error is raised.

πŸ™‚ Expected behavior

I expect the result of the imported JSON to be identical to when directly assigning the values in the typescript file. The contents of the JSON array are known at compile time, so there is no need to raise ts2322.

Additional information about the issue

I suspect ts converts the type of the imported field to number[] and not to [number, number].

@fatcerberus
Copy link

fatcerberus commented Jun 1, 2024

This is more or less equivalent to

const test = [
  {
    "field": [1, 200]
  }
];
const t: MyType[] = test;

which has the same error (for the same reason).

@MartinJohns
Copy link
Contributor

You would need something like #32063.

@jcalz
Copy link
Contributor

jcalz commented Jun 1, 2024

Yeah, I'd consider this a duplicate of #32063

@MarByteBeep
Copy link
Author

Even though I see the similarities, I think that proposal goes a bit further (and will probably fix this as well). In my case TS incorrectly flags this as an error, even though it shouldn't. Hopefully this is easier to fix than #32063, as that one has been open for 5 years already...

@MartinJohns
Copy link
Contributor

In my case TS incorrectly flags this as an error, even though it shouldn't.

It doesn't flag it incorrectly as an error. You're just wrongly assuming the imported JSON has a narrowed type (the tuple), when it's just the widened type (an array). You expect a feature that's not supported.

@MarByteBeep
Copy link
Author

Look, I'm just reporting in my opinion inconsistent behavior. When doing seemingly identical operations (direct assignment vs assignment through a JSON import), I get different results and spent a long time figuring out why.

I understand now why that happens, but from a design perspective this is not very intuitive. Just my two cents.

@fatcerberus
Copy link

fatcerberus commented Jun 1, 2024

@MarByteBeep The inconsistent behavior is the same as what's illustrated in my post above. The direct assignment works because there's a contextual type that TS can use as a hint to avoid widening too far. In the case of the indirect assignment, that doesn't happen and the object literal widens, leading to an assignability error down the line. That widening is by design, and the JSON import isn't special in that regard.

The only difference is that, for an object literal written inline, you can write { ... } as const to prevent widening, while there's no equivalent syntax for imports. That's what #32063 is about.

@MarByteBeep
Copy link
Author

Got it. Thanks for elaborating that!

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 13, 2024
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

6 participants