-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[MM-20522] Migrate rhs_card to TypeScript #5354
[MM-20522] Migrate rhs_card to TypeScript #5354
Conversation
enablePostIconOverride: PropTypes.bool.isRequired, | ||
hasImageProxy: PropTypes.bool.isRequired, | ||
enablePostIconOverride: PropTypes.bool, | ||
hasImageProxy: PropTypes.bool, |
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.
Direct quote from Abdusabri's PR (link):
The component was already used without providing
enablePostIconOverride
andhasImageProxy
props. Like:const avatar = ( <PostProfilePicture compactDisplay={false} post={selected} userId={selected.user_id} /> );So, had to make them optional because TypeScript was complaining about this 🙂
isBusy: PropTypes.bool, | ||
isRHS: PropTypes.bool, | ||
post: PropTypes.object.isRequired, | ||
status: PropTypes.string, | ||
user: PropTypes.object, | ||
isBot: PropTypes.bool, | ||
postIconOverrideURL: PropTypes.string, | ||
userId: PropTypes.string |
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.
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.
It doesn't appear to be used in this component though, so we should remove it and all references to it instead.
}; | ||
|
||
export type PostPluginComponent = { | ||
id: string; | ||
pluginId: string; | ||
type: string; | ||
component: React.Component; | ||
component: React.ComponentType<{post: Post}>; |
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.
Direct quote from Abdusabri's PR (link):
When a react component is used like in the following code snippet:
if (pluginPostCardTypes.hasOwnProperty(postType)) { const PluginComponent = pluginPostCardTypes[postType].component; content = <PluginComponent post={selected}/>; }TypeScript is looking for a type not a constructor function, so it was giving an error that the
PluginComponent
variabledoes not have any construct or call signatures
. So, had to change it.Here are couple of links for reference:
@@ -17,5 +19,3 @@ export type RhsViewState = { | |||
isSidebarExpanded: boolean; | |||
isMenuOpen: boolean; | |||
}; | |||
|
|||
export type RhsState = 'mention' | 'search' | 'flag' | 'pin' | 'plugin'; |
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.
This type was only used from components/rhs_card
and from this file. Every occurrence was replaced with ValueOf<typeof RHSStates>
import solarizedLightCSS from '!!file-loader?name=files/code_themes/[hash].[ext]!highlight.js/styles/solarized-light.css'; // eslint-disable-line import/order | ||
import solarizedLightCSS from '!!file-loader?name=files/code_themes/[hash].[ext]!highlight.js/styles/solarized-light.css'; | ||
|
||
export type ValueOf<T> = T[keyof T]; |
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.
This generic type allows getting union of values from a const object in a single line: ValueOf<typeof my_obj>
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 think we're good with this. Thanks :)
|
||
export const RHSStates = { | ||
MENTION: 'mention', | ||
SEARCH: 'search', | ||
FLAG: 'flag', | ||
PIN: 'pin', | ||
PLUGIN: 'plugin', | ||
}; | ||
} as const; |
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.
Allows for ValueOf<typeof RHSStates>
instead of 'mention' | 'search' | 'flag' | 'pin' | 'plugin'
Permissions.MANAGE_CREATE_EMOJIS, | ||
Permissions.MANAGE_DELETE_EMOJIS, | ||
Permissions.CREATE_EMOJIS, | ||
Permissions.DELETE_EMOJIS, |
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.
This change is based on the fact that at the time these two lines were added (and now as well), there were no such permissions in mattermost-redux/src/constants/permissions.js
and no such permissions were referenced in mattermost-web
nor mattermost-redux
.
Commits that introduced this change:
- mattermost-webapp: Using new splited emojis and webhooks permissions (#2339)
- mattermost-redux: Splitting emojis and webhooks permissions (#4532)
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.
Updating mattermost-redux
to the latest commit and updating your branch to master
should resolve the need for this.
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.
Hmm, I've fetched master for both mattermost-webapp
and mattermost-redux
and I've run npm update
afterwards, but this line still gives me an error TS2551: Property 'MANAGE_CREATE_EMOJIS' does not exist on type (...)
and same for MANAGE_DELETE_EMOJIS
. I also don't see them in mattermost-redux/src/constants/permissions.ts.
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.
@jespino Should utils/constants.tsx
be updated on master
here?
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.
Yes, I think so, I think the current state is a bug, and we should change that.
@AkaZecik Thanks for opening this PR! I've queued it for review. Heads up that there is a merge conflict. Would you please resolve it? Also the CI failed with:
Please let me know if you need help resolving the failure. |
Merge conflicts are now resolved, I must have pulled from my fork's master. Sorry for that.
Those lines fail, because I changed the extension from |
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.
Thanks for the contribution @AkaZecik, I have some comments shown below.
isBusy: PropTypes.bool, | ||
isRHS: PropTypes.bool, | ||
post: PropTypes.object.isRequired, | ||
status: PropTypes.string, | ||
user: PropTypes.object, | ||
isBot: PropTypes.bool, | ||
postIconOverrideURL: PropTypes.string, | ||
userId: PropTypes.string |
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.
It doesn't appear to be used in this component though, so we should remove it and all references to it instead.
components/rhs_card/rhs_card.tsx
Outdated
pluginPostCardTypes: PluginsState['postCardTypes']; | ||
previousRhsState?: ValueOf<typeof RHSStates>; | ||
enablePostUsernameOverride?: boolean; | ||
teamUrl: string; |
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.
Should be optional according to the original spec.
components/rhs_card/rhs_card.tsx
Outdated
|
||
interface Props { | ||
selected?: Post; | ||
pluginPostCardTypes: PluginsState['postCardTypes']; |
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.
Should be optional according to the original spec.
components/rhs_card/rhs_card.tsx
Outdated
previousRhsState?: ValueOf<typeof RHSStates>; | ||
enablePostUsernameOverride?: boolean; | ||
teamUrl: string; | ||
channel?: Channel; |
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.
This isn't used in the component anywhere and should be removed.
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.
It was present in tests, so I decided to include it here. I will remove it from there as well
components/rhs_card/rhs_card.tsx
Outdated
teamUrl: PropTypes.string, | ||
} | ||
export default class RhsCard extends React.Component<Props, State> { | ||
state: State; |
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.
state
is already a property of React.Component
, you don't need to declare it.
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 added it based on this suggestion from react-typescript-cheatsheet (there is a subsection called 'Why annotate state
twice?', which references awesome advice from Ferdaber #57)
I can remove it, if you prefer
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.
We usually do it in the constructor if it is required. If we aren't using state
at all then we just don't declare the type. I haven't run into any issues using this.setState
with TypeScript so I think we're okay to remove it.
types/store/plugins.ts
Outdated
}; | ||
|
||
export type AdminConsolePluginComponent = { | ||
pluginId: string; | ||
key: string; | ||
component: React.Component; | ||
component: React.ComponentType<any>; |
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.
Is this really any
component or is it a certain subset of components? We try to avoid any
so it'd be nice to type this.
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 tried to go through it's usages, but I couldn't find anything that would suggest it's shape. I could replace any
with {}
which would postpone this problem to whenever some other migration from JS to TS that uses it would start complaining. Running npm run check-types
with {}
instead of any
reports no new errors. What are your thoughts?
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.
Both are kinda the same thing, since they basically just short-circuit type checking by allowing basically anything. Usually the type checker should throw an error if you type it wrong, so maybe that could suggest it's shape? I'm 2/5 on this, if it's too much effort I'm okay with a comment explaining why the any
or {}
was used.
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.
Wouldn't React.ComponentType<{}>
allow only for components without any properties? For example, when I remove {post: Post}
from above, I get an error here: components/rhs_card/rhs_card.tsx:120.
With {}
, instantiating a component with any props would raise an error and would require an update to the shape here.
I will try to dig deeper to find a shape, I will let you know how it goes
Permissions.MANAGE_CREATE_EMOJIS, | ||
Permissions.MANAGE_DELETE_EMOJIS, | ||
Permissions.CREATE_EMOJIS, | ||
Permissions.DELETE_EMOJIS, |
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.
Updating mattermost-redux
to the latest commit and updating your branch to master
should resolve the need for this.
import solarizedLightCSS from '!!file-loader?name=files/code_themes/[hash].[ext]!highlight.js/styles/solarized-light.css'; // eslint-disable-line import/order | ||
import solarizedLightCSS from '!!file-loader?name=files/code_themes/[hash].[ext]!highlight.js/styles/solarized-light.css'; | ||
|
||
export type ValueOf<T> = T[keyof T]; |
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 think we're good with this. Thanks :)
- remove userId from PostProfilePicture and all references to it - remove channel from RhsCard and it's tests - make teamUrl optional in RhsCard - remove explicit declaration of state in RhsCard - change shape of component from any to {} (temporary)
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.
🎉LGTM
This issue has been automatically labelled "stale" because it hasn't had recent activity. /cc @jasonblais @hanzei |
/update-branch |
Error trying to update the PR. |
@devinbinnie I believe this is pending your review next. Are you open to helping with that? |
Hey @AkaZecik, looks like we have some type checking errors on this PR. Can you resolve those and update the branch to master before we proceed? Thanks :) |
Hi, sorry for the delays, I'm quite busy recently. If anyone wants to pick this up, feel free to go. Otherwise, when I find a spare time and it stays in the same place, I will fix it, but I can't give the time yet. From what I remember, there was an issue with webpack in file |
@AkaZecik What I think we can do here for now is to add our own module for That should take care of those particular TS errors. |
This PR has been automatically labelled "stale" because it hasn't had recent activity. /cc @jasonblais @jfrerich |
@devinbinnie, @calebroseland, @jespino it sounds like the author is quite busy. Any chance one of you could pick up the PR and push it through? |
Thanks, @jespino and I agree we should wait for approval from @AkaZecik :) If you don't feel there is a rush to complete this PR, that's fine too. I recently took ownership of addressing the stale tickets (from |
Hi, I'm OK with one of you finishing this PR 😃 I can't tell when I will have time to do it myself and I would rather not stall any progress here |
@jespino @devinbinnie @calebroseland Is one of you picking up this PR? |
@hanzei Not sure if any of us have time to do so, would it be alright to open the ticket to Up for Grabs again with this PR as a starting point for any contributor to finish it off? |
@AkaZecik Would you be fine closing your PR and using the as a starting point for another community member? |
It's ok :) I will reopen it if I come back to this issue before anyone else. |
Summary
Migrates
components/rhs_card
to TypeScriptTicket Link
Fixes mattermost/mattermost#13718
Description
There are 4 commits. First two migrate
components/rhs_card
to TypeScript. Last two attempt to remove redundancy by marking constantsas const
. The problem is that if we wanted to get a type which is equal to a union of values from an object, we had to extract them manually:By marking
RHSStates
as const
, we can extract values automatically:Withouth
as const
, the type in the last line would bestring
instead (due to type widening).First two commits pass
npm run check-types
and completely solve the mentioned ticket.However, last two commits don't, because TypeScript can't resolve webpack's inline loaders in
utils/constants.tsx
(there are four imports, all of formimport SomeCSS from '!!file-loader?name=files/code_themes/[hash].[ext]!highlight.js/styles/FILE.css'
).I've spent quite some time researching what the reason is and how to solve it, but unfortunately I wasn't able.
If you prefer, you can revert last two commits from this PR and merge it, or perhaps make some changes to webpack's/typescript's configuration so that those 4 imports won't offend TypeScript anymore :)
Many thanks to Abdusabri (for this reason 🥇).