|
| 1 | +# Code conventions |
| 2 | + |
| 3 | +Some conventions we are using related to the project structure, TypeScript, etc, to improve consistency and facilitate maintenance. |
| 4 | + |
| 5 | +## Utils |
| 6 | + |
| 7 | +Utility functions (utils) should be defined in standalone files inside `src/lib/utils` dir. |
| 8 | + |
| 9 | +## Scripts |
| 10 | + |
| 11 | +Scripts we use on build time and are not directly related to the source code (eg: Crowdin imports, GitHub tasks) should be defined in standalone files inside `src/scripts` dir. |
| 12 | + |
| 13 | +## Constants |
| 14 | + |
| 15 | +Global constants should be defined inside `src/lib/constants.ts` file. |
| 16 | + |
| 17 | +## TypeScript |
| 18 | + |
| 19 | +### Types |
| 20 | + |
| 21 | +TypeScript types should be defined inside `src/lib/types.ts` file. Note that some pre-existent types could be defined in other files and will be temporarily kept there during the migration, to facilitate synchronization. These types should be moved to `src/lib/types.ts` later. |
| 22 | + |
| 23 | +### Interfaces |
| 24 | + |
| 25 | +TypeScript types should be defined inside `src/lib/interfaces.ts` file. Note that some pre-existent interfaces could be defined in other files and will be temporarily kept there during the migration, to facilitate synchronization. These interfaces should be moved to `src/lib/interfaces.ts` later. |
| 26 | + |
| 27 | +### Component Props |
| 28 | + |
| 29 | +For all components, use the following pattern: |
| 30 | + |
| 31 | +```tsx |
| 32 | +type ComponentProps = { |
| 33 | + // Prop types |
| 34 | +} |
| 35 | + |
| 36 | +// Destructure props at the declaration and use the name `props` when using the spread operator for the remaining props not specifically needed |
| 37 | +const Component = ({ title, label, ...props }: ComponentProps) => { |
| 38 | + // Component code |
| 39 | +} |
| 40 | + |
| 41 | +/** |
| 42 | + * Components using `forwardRef` from the Chakra UI package |
| 43 | + * |
| 44 | + * The first argument of the generic types is the props type signature. |
| 45 | + * |
| 46 | + * For the second argument of the generic types, you are declaring the primary element type that the component will render. |
| 47 | + * This could be a `div`, `span`, `button`, etc. or a custom component (typeof Button) if said component is being used in the return. |
| 48 | + */ |
| 49 | +const Component = forwardRef<ComponentProps, "div">( |
| 50 | + ({ title, label, ...props }, ref) => { |
| 51 | + // Component code |
| 52 | + } |
| 53 | +) |
| 54 | +``` |
| 55 | + |
| 56 | +#### Prop Type Naming Convention |
| 57 | + |
| 58 | +For the props type signature use the naming convention `<ComponentName>Props` to provide an explicit name for the type. This is helpful for importing the signature to other files like page component and not force the user to alias the import every time, while providing readability. |
| 59 | + |
| 60 | +#### Directly annotate the props object |
| 61 | + |
| 62 | +**Do not use `React.FC`** and instead annotate the props object directly. `React.FC` implies the `children` prop, but this is not always desired when there is a component that should not accept this prop. `React.FC` also does not allow for use of Generic types, or use of Generic type when doing type guarding like function overloading. It is also not generally recommended to use and [was removed from the create-react-app template](https://github.com/facebook/create-react-app/pull/8177). |
| 63 | + |
| 64 | +A positive side-effect to directly annoting the props object is for IDE intellisense where you can view the props when hovering over the component name to see it's signature. |
| 65 | + |
| 66 | +i.e. `const Component: ({ label, title, ...props }: ComponentProps) => React.JSX.Element` |
| 67 | + |
| 68 | +#### Use the type alias for props type |
| 69 | + |
| 70 | +Use `type` and not `interface` to have the most constraint on the signature. We should also not be modifying the signature such as using [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces). |
0 commit comments