-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[No QA] Add TypeScript Guideline #21549
Conversation
@stitesExpensify Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
We lack couple of sections from the original guidelines:
What do you think, should we include them here? @hayata-suenaga @fabioh8010 |
fyi @hayata-suenaga @fabioh8010 You can view it directly in this repo, the easiest way is to click on the file options -> "View file" |
contributingGuides/TS_STYLE.md
Outdated
<a name="convension-export-prop-types"></a><a name="1.14"></a> | ||
|
||
- [1.14](#convension-export-prop-types) **Prop Types**: Define and export prop types for components. Use exported prop types instead of grabbing the prop type from a component. | ||
|
||
> Why? Exporting prop types aids reusability. | ||
|
||
```tsx | ||
// MyComponent.tsx | ||
export type MyComponentProps = { | ||
foo: string; | ||
}; | ||
|
||
export default function MyComponent({ foo }: MyComponentProps) { | ||
return <Text>{foo}</Text>; | ||
} | ||
|
||
// bad | ||
import { ComponentProps } from "React"; | ||
import MyComponent from "./MyComponent"; | ||
type MyComponentProps = ComponentProps<typeof MyComponent>; | ||
|
||
// good | ||
import MyComponent, { MyComponentProps } from "./MyComponent"; | ||
``` |
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.
@hayata-suenaga Are we going to always export the component's props, even when isn't necessary? cc @blazejkustra
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.
When props are only used inside of the file where it is declared I wouldn't export 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.
From previous guidelines PR:
Types specific to a single file should remain inside that file to keep their scope limited and their usage clear.
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.
When props are only used inside the file where it is declared, I wouldn't export it.
I was thinking it might be a good idea to always export a prop type if its component is also exported. We don't know if other components might need the prop type or not
what do you think @fabioh8010 @blazejkustra
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 don't have a strong opinion here but, it can lead to a sort of "premature optimization". We should not export props just in case they might be needed in the future (YAGNI principle).
Instead, if such need arises where props are required in another component, we can start exporting them at that time. @hayata-suenaga
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 would prefer to not export every prop type as they are going to "pollute" the editor's autocomplete mechanisms unnecessarily, we should export only things that are going to be used across the project.
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.
okay that makes sense removing this part. should we allow the usage of type MyComponentProps = ComponentProps<typeof MyComponent>;
or if the prop type is needed, should they be exported?
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.
@hayata-suenaga @blazejkustra I think it's better to export the prop type itself when needed instead of using ComponentProps
👍
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.
okay then let's include instructions to export and import prop types if you find yourself trying to use ComponentProps
what do you think @blazejkustra
@hayata-suenaga I agree with @blazejkustra about the missing sections. Is there a reason for removing them or are you still working on this PR? |
I'm marked this as a draft since @hayata-suenaga's latest comment on Slack says he still needs to add some pieces. |
@fabioh8010 @blazejkustra thank you for your quick review 👍 I still have mission sections. I added a TODO list in the initial message of this PR, and I'll update them as I go |
contributingGuides/TS_STYLE.md
Outdated
<a name="convension-export-prop-types"></a><a name="1.14"></a> | ||
|
||
- [1.14](#convension-export-prop-types) **Prop Types**: Define and export prop types for components. Use exported prop types instead of grabbing the prop type from a component. | ||
|
||
> Why? Exporting prop types aids reusability. | ||
|
||
```tsx | ||
// MyComponent.tsx | ||
export type MyComponentProps = { | ||
foo: string; | ||
}; | ||
|
||
export default function MyComponent({ foo }: MyComponentProps) { | ||
return <Text>{foo}</Text>; | ||
} | ||
|
||
// bad | ||
import { ComponentProps } from "React"; | ||
import MyComponent from "./MyComponent"; | ||
type MyComponentProps = ComponentProps<typeof MyComponent>; | ||
|
||
// good | ||
import MyComponent, { MyComponentProps } from "./MyComponent"; | ||
``` |
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.
From previous guidelines PR:
Types specific to a single file should remain inside that file to keep their scope limited and their usage clear.
I went through the previous PR and compared it to @hayata-suenaga version. Added couple of suggestions on what we are missing and would be awesome to include it. I want to make these TS conventions as clear as possible to contributors. cc @hayata-suenaga @fabioh8010 |
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.
Let's do this thing!
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.
Couple questions/clarifications, otherwise LGTM 👍🏼
function MyComponent({ | ||
requiredProp, | ||
optionalPropWithDefaultValue = 42, | ||
optionalProp, |
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 all optional props be required to have a default?
I don't feel strongly either way, but we should clarify that here because currently all optional props are required to have a default.
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.
agree we should clarify on this. if you don't pass anything to an optional prop and a default value is not provided, the value for that prop is undefined
.
If the prop can be undefined
and the component implementation can handle that situation, then we don't have to require default props to be passed always.
in other words, if the default value is undefined
(or null
), default value is not needed imo
I gonna post this to ask if everyone feels okay changing the rule in the open source channel as this changes the current guideline
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.
Agree with your suggestion
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.
Looking great 🚀
904c6d6
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.
@hayata-suenaga Some nitpicks but overall is looking great, approved 🚀
contributingGuides/TS_STYLE.md
Outdated
|
||
> Refer to [the propTypes Migration Table](./PROPTYPES_CONVERSION_TABLE.md) on how to type props based on existing `propTypes`. | ||
|
||
> Assign a default value to each optional prop unless the default values is `undefined` or `null`. |
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.
@hayata-suenaga Please see my comment on Slack regarding null
.
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 ended up removing null
from the text and made it
unless the default values is `undefined`
putting null
here might cause confusion and there might be code that checks for if (
prop===
null)
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.
Looking good, thanks for making the changes I suggested. I agree with Fábio's comments too.
thank you everyone for detailed reviews 🙇 if this PR looks good, could someone do a PR reviewer checklist please 🙇 |
Reviewer Checklist
Screenshots/VideosNo videos, this is a markdown change only. WebMobile Web - ChromeMobile Web - SafariDesktopiOSAndroid |
@hayata-suenaga you can include an author checklist to make the checks pass or we can just merge with failing checks and explain why. |
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! Left some typo comments.
8b3bad5
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/hayata-suenaga in version: 1.3.45-0 🚀
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.3.45-7 🚀
|
Built upon the guideline PR by @fabioh8010 and @blazejkustra. Further iteration on #21050
$ #20623
NO QA/TEST
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
N/A
Mobile Web - Chrome
N/A
Mobile Web - Safari
N/A
Desktop
N/A
iOS
N/A
Android
N/A