-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[typescript] Enable generic props for certain components #13868
Conversation
@@ -14,7 +14,8 @@ import TextField from '@material-ui/core/TextField'; | |||
variant="standard" | |||
InputProps={{ | |||
// notchedOutline is only used with variant "outlined" | |||
classes: { inputTypeSearch: 'search-input', notchedOutline: 'notched-outline' }, // $ExpectError | |||
// FIXME this no longer generates an error in TS 3.2, see https://github.com/Microsoft/TypeScript/issues/28926 | |||
// classes: { inputTypeSearch: 'search-input', notchedOutline: 'notched-outline' }, // $ExpectError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upgrading TypeScript broke this test, due to microsoft/TypeScript#28926.
@pelotom I did commit some changes from my own review that I thought weren't that controversial. This includes some code comments for the types. Could you go over some unaddressed review comments? I think we can start converting the other declarations and get some feedback on a alpha release. |
@eps1lon very sorry I've been AWOL on this, work has been crazy. I should have time to look this over tonight. |
No worries. I think I only fixed some nitpicks I had. Looks like we can start applying this to the rest of the components which hopefully is pretty straight forward and doesn't break any tests. |
I assume you mean merge this and then start to gradually migrate other components to the new system, yeah? |
@@ -163,7 +163,7 @@ const BottomNavigationTest = () => { | |||
const value = 123; | |||
|
|||
return ( | |||
<BottomNavigation value={value} onChange={e => log(e)} showLabels> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of writing these as lambdas was to ensure that the argument type was being inferred...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it complain that log
is not assignable to (e: EventType) => ReturnType
in those cases? What makes this different from the cases where you added an explicit ExpectType
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it complain that
log
is not assignable to(e: EventType) => ReturnType
in those cases?
Perhaps it should, but it doesn't.
What makes this different from the cases where you added an explicit
ExpectType
?
It's a less rigorous test (just that something other than any
was inferred for the argument, not making an assertion about what was inferred). There's no reason an ExpectType
couldn't be added also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you quickly push a test that is not throwing when it should for my own peace of mind? Just want to make sure we're not disabling some lint rule that was removed because of something unrelated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I don't think I follow. Could you elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn’t test inference because you’re passing a function whose signature is already determined. The point is to pass an inline function with no parameter signature so that if it can’t infer the type there will be a noImplicitAny
error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is to pass an inline function with no parameter signature so that if it can’t infer the type there will be a
no-implicit-any
error.
Ah now I understand. Happy to revert a7f6d4c then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we didn’t want to disable the lint rule we could just as well pass e => {}
to test this, the log
call is unimportant... but IIRC the only reason for it was to appease another lint rule for unused variables.
Probably should just selectively disable the lint rule for these lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with disabling the rule since our ts files never make it to runtime anyway. I would say that the only useful pattern the lint rule flags is in react props. A new callback could defeat memoized components.
The ts files in our docs are transpiled to JS at which point eslint would cover that case.
If end up disabling the rules for every instance of unnecessary callbacks then we might as well disable it globally (or maybe starting with per file disables)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I reverted 79c4872.
* Changed the Tab component to work with generic props (see #13868) * successfully run yarn prettier with the correct config * successfully ran yarn typescript
This revives the effort started in #11731, which ran into difficulty with callback parameter types no longer being inferred, thus breaking backwards compatibility. This new approach circumvents the issue by using overloads; in the simple case where no override
component
is provided, callback parameter types are fully inferred with no extra work. In the case where an overridecomponent
is provided, you can eithercomponent
prop:So far in this PR only a handful of components have been converted to use this new typing strategy:
Avatar
Button
Fab
ListItem
Tabs
The results seem promising, but I wanted to solicit feedback before diving in too much deeper. One unfortunate issue is that error messages can be somewhat cryptic; for instance with
The error we get is that
Property 'component' does not exist on type ...
. There is an error here, which is that we are providing a prop,onClick
, which does not exist on the overriding component, however the message doesn't help us understand that.Upgraded TypeScript to 3.2 because it contains a bugfix for microsoft/TypeScript#26004 which is necessary to make this work.