Skip to content

JSX errors use JSX terminology #24523

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
wants to merge 5 commits into from
Closed

Conversation

sandersn
Copy link
Member

@sandersn sandersn commented May 31, 2018

Well, as well as I understand it. Regardless, the error message no
longer mentions a complex synthetic type that represents the
component. It just mentions the name of the component.

Doesn't fix a specific bug, just makes everybody's life better.

Edit: The PR now simplifies the elaboration instead of the head message.

Well, as well as I understand it. Regardless, the error message no
longer mentions a complex synthetic type that *represents* the
component. It just mentions the name of the component.
!!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'.
!!! error TS2322: Type '{}' is not assignable to type '{ reqd: any; }'.
!!! error TS2322: Property 'reqd' is missing in type '{}'.
!!! error TS2610: The attributes provided to T are not assignable to type 'IntrinsicAttributes & { reqd: any; }'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See what's going on here (unrelated)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second change in this test also shows off that we need to print entitynames, not just identifiers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like IntrinsicAttributes is defined, but IntrinsicClassAttributes isn't. The predicate needs to give up a little less easily.

@weswigham
Copy link
Member

IMO, an error like this is useless when it comes to actually fixing the problem if there's no elaboration. (Since then it doesn't mention where the issue is in the type, nor what the witnessed type actually is.) Which means if the same assignability error occurs twice in your program (potentially in very different places), and you happen to be looking at the elaboration-less site in your editor, fixing the problem could be quite the head-scratcher! While it may make the error less wordy, it removes a fair amount of utility, so I'm unsure about it.

1. also remove "the component" fallback -- replace with an assert
2. Also add quotes around the component's name
@sandersn
Copy link
Member Author

An error happening twice

  1. Is rare (except when porting an existing program, but certainly when composing a new one).
  2. Is not an issue in a real program since you'll be looking at the all the errors, and will presumably read them from top to bottom, so will see the elaborated version first.

The value of having an error message that JSX programmers can read far outweighs the problems with the unelaborated version. Specifically, the type literal that is synthesised from the component is foreign and confusing and I suspect that it makes new Typescript users stop reading.

@weswigham
Copy link
Member

weswigham commented May 31, 2018

Is rare

Change a prop type used at multiple callsites (eg, a library or lib updates underneath you). Bam, multiple errors involving the same types.

Is not an issue in a real program since you'll be looking at the all the errors, and will presumably read them from top to bottom, so will see the elaborated version first.

90% of the time, I only look at the squiggles in the editor plus their messages and not the error output (this is mostly a workflow thing - I generally only use the error list to check for nonlocal errors); meaning I only immediately see errors around my current context unless I go looking for them.

Specifically, the type literal that is synthesised from the component is foreign and confusing and I suspect that it makes new Typescript users stop reading.

Just because the input looks like jsx instead of an object literal? I'm not sure I buy it. The shape's the same, it's just syntax that differs.

For comparison, the error

Type assigned to variable "x" which expects type "Foo" did not match.

Would be the analagous error for object literals, and I think that would be unambiguously worse, so why would the jsx error be any better?

Like, the tag name/variable name adds no more context than the error span itself (after all, the tag is readable there), so is extra info already provided elsewhere, so all you're doing is eliding half of the error and consequentially making it impossible to distinguish just from the error what went wrong (am I missing a literal type I expected? Is something an array when it shouldn't be?)

@sandersn
Copy link
Member Author

@weswigham Let's talk about it in person with @RyanCavanaugh.

@sandersn
Copy link
Member Author

We had a long in-person discussion. I'll try to summarise. First, the things we agreed on (I think -- feel free to chime in):

  1. The main place this error happens is in the case that the component is missing an attribute. The children type could be wrong, but this doesn't happen much.
  2. The top-level error line is not often useful -- both now, and after this change. Before, it lists a source type when only the property names even matter, and after the type is gone entirely. Ideally, the top-level error would be a combination of the first two error lines: "Property 'P' is required by type 'Target' but was not provided." No elaboration.
  3. This is a general problem that object literal assignment shares with JSX components.
  4. Even more generally, nested object literals (and JSX components with attributes with nested literal types) should drill down, discarding outer error messages until the first mismatch is encountered.

(4) is hard to implement, and the discard-drill-down idea needs some design thought in addition. I will try to specify it more carefully in a later post.

What we did not agree on is whether this change is an improvement without an elaboration. However, this is a moot point. JSX components are treated just like object literals, and multiple identical components are distinct, so each error has an elaboration.

@weswigham
Copy link
Member

(4) is hard to implement, and the discard-drill-down idea needs some design thought in addition. I will try to specify it more carefully in a later post.

I have a branch with an implementation. It's often terser, for sure, but as I said in person - without related spans to retain some of the original context, I'm not very comfortable pushing it.

@sandersn
Copy link
Member Author

In the meantime, I simplified the elaboration to mention JSX explicitly, and returned the head message to its original state. We might be able to generalise this change if we decide to implement related spans.

@weswigham
Copy link
Member

@sandersn Now that my deeper elaborations (with related spans!) are in, what do you think about this?

@RyanCavanaugh
Copy link
Member

@sandersn let's either refresh or close this

@sandersn
Copy link
Member Author

sandersn commented Sep 5, 2018

This is outdated now, so I'l close it.

@sandersn sandersn closed this Sep 5, 2018
@sandersn sandersn deleted the even-simpler-jsx-error-messages branch September 5, 2018 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants