Skip to content

Commit

Permalink
Add style guides for TypeScript, React, and Jest (#603)
Browse files Browse the repository at this point in the history
  • Loading branch information
WilHall authored Jun 12, 2020
1 parent 6d86958 commit e6e46a2
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 2 deletions.
7 changes: 5 additions & 2 deletions style/javascript/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
JavaScript
==========
# JavaScript

[Sample](sample.js)

* Use [ESlint] and [Prettier] for auto-formatting and auto-fixing
* Use [Jest](../testing-jest/README.md) for unit testing
* Prefer ES6 classes over prototypes.
* Use strict equality checks (`===` and `!==`) except when comparing against
(`null` or `undefined`).
Expand All @@ -24,6 +25,8 @@ JavaScript
* Use a [trailing comma] after each item in a multi-line array or object
literal, including the last item.

[eslint]: https://eslint.org/
[prettier]: https://prettier.io/
[template strings]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
[arrow functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[destructuring]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Expand Down
42 changes: 42 additions & 0 deletions style/react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# React

- Start new projects with [react-suspenders]
- Use React in [Strict Mode]
- Use React with [TypeScript](../typescript/README.md)
- Avoid nested routing if using [React Router]
- Prefer [Function Components] over [Class Components]
- Prefer keeping a single component in each file
- Use `PascalCase` for component names and their file names
- Use [React Hooks]
- Use pre-built hooks when possible (e.g. [streamich/react-use])
- Use [custom hooks] to encapsulate stateful logic outside a component
- Avoid nesting [Forward Refs]
- Avoid [Higher-Order Components] and [recompose] (see hooks above as an alternative)
- Prefer the `children` prop over [render props]
- Prefer using [TypeScript prop interfaces] over [PropTypes]
- Prefer the [short syntax] when using [Fragments]
- Prefer [React Contexts] over [Redux]
- Avoid using indexes as the value for [keys]
- Prefer [component composition over component inheritance]

[react-suspenders]: https://github.com/thoughtbot/react-suspenders
[strict mode]: https://reactjs.org/docs/strict-mode.html
[react hooks]: https://reactjs.org/docs/hooks-overview.html
[custom hooks]: https://reactjs.org/docs/hooks-overview.html#building-your-own-hooks
[streamich/react-use]: https://github.com/streamich/react-use
[graphql]: https://graphql.org/
[function components]: https://reactjs.org/docs/components-and-props.tml
[class components]: https://reactjs.org/docs/react-component.html
[forward refs]: https://reactjs.org/docs/forwarding-refs.html
[higher-order components]: https://reactjs.org/docs/higher-order-components.html
[recompose]: https://github.com/acdlite/recompose
[render props]: https://reactjs.org/docs/render-props.html
[typescript prop interfaces]: https://www.typescriptlang.org/docs/handbook/react-&-webpack.html#write-some-code
[proptypes]: https://reactjs.org/docs/typechecking-with-proptypes.html
[short syntax]: https://reactjs.org/docs/fragments.html#short-syntax
[fragments]: https://reactjs.org/docs/fragments.html
[react contexts]: https://reactjs.org/docs/context.html
[redux]: https://react-redux.js.org/
[keys]: https://reactjs.org/docs/lists-and-keys.html#keys
[component composition over component inheritance]: https://reactjs.org/docs/composition-vs-inheritance.html
[react router]: https://reacttraining.com/react-router/
25 changes: 25 additions & 0 deletions style/testing-jest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Testing with Jest

See also [Testing](../testing/README.md).

- Use [eslint-plugin-jest] to enforce testing style
- Use [testing-library/jest-dom] and [jest-community/jest-extended] for supplemental expectation matchers
- Use [React Testing Library] for testing [React](../react/README.md) components
- Use [React Hooks Testing Library] for testing [React Hooks]
- Use [User Event] for simulating DOM events on React components under test
- Use [Fishery] for building factories
- Prefer placing test suite files alongside source files (e.g. `Thing.tsx` / `Thing.test.tsx`)
- Prefer writing specific unit tests over [Snapshot Testing]
- Prefer `describe` and `it` blocks over `test` blocks
- Prefer [.resolves/.rejects] over awaiting promises in tests

[eslint-plugin-jest]: https://github.com/jest-community/eslint-plugin-jest
[testing-library/jest-dom]: https://github.com/testing-library/jest-dom
[react testing library]: https://github.com/testing-library/react-testing-library
[react hooks testing library]: https://github.com/testing-library/react-hooks-testing-library
[react hooks]: https://reactjs.org/docs/hooks-overview.html
[user event]: https://github.com/testing-library/user-event
[fishery]: https://github.com/thoughtbot/fishery
[snapshot testing]: https://jestjs.io/docs/en/snapshot-testing
[jest-community/jest-extended]: https://github.com/jest-community/jest-extended
[.resolves/.rejects]: https://jestjs.io/docs/en/asynchronous#resolves--rejects
57 changes: 57 additions & 0 deletions style/typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# TypeScript

- Use the guidelines for [JavaScript](../javascript/README.md)
- Use TypeScript in [strict mode]
- Use [ESlint] and [Prettier] for auto-formatting and auto-fixing
- Use [Jest](../testing-jest/README.md) for unit testing
- Prefer [Functions] over [Classes]
- Prefer functional style (map/filter/reduce) over iteration (for/while/.each)
- Prefer [arrow functions] `=>`, over the `function` keyword except when using [Generics]
- Use [Generic Constraints] when possible
- Use `PascalCase` for [Interfaces] and [Type Aliases]
- Use [readonly] properties where applicable
- Use [Const Assertions] where applicable to avoid type widening
- Avoid complex conditionals inside TSX
- Avoid [Mixins]
- Avoid [Decorators]
- Avoid [Overloading Functions]
- Prefer [async/await] over traditional promise syntax
- Prefer [Optional Properties] in an interface rather than declaring the property type as `T | undefined`
- Prefer explicitly defining interfaces over [Extending Interfaces]
- Avoid the use of the [any] type
- Avoid the [Non-null assertion operator]
- Avoid [Type Assertions]
- Prefer the `as`-syntax for [Type Assertions] over the angle-bracket syntax
- Use the [Nullish coalescing operator]
- Prefer [Type Guards] over [Type Assertions]
- Prefer [Union Types], [Lookup Types], [Mapped Types] and [Const Assertions] over [Enums]

[eslint]: https://eslint.org/
[prettier]: https://prettier.io/
[functions]: https://www.typescriptlang.org/docs/handbook/functions.html
[classes]: https://www.typescriptlang.org/docs/handbook/classes.html
[arrow functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[generics]: https://www.typescriptlang.org/docs/handbook/generics.html
[generic constraints]: https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints
[readonly]: https://www.typescriptlang.org/docs/handbook/interfaces.html#readonly-properties
[strict mode]: https://www.typescriptlang.org/docs/handbook/compiler-options.html
[non-null assertion operator]:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator
[nullish coalescing operator]:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing
[extending interfaces]: https://www.typescriptlang.org/docs/handbook/interfaces.html#extending-interfaces
[optional properties]: https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties
[interfaces]: https://www.typescriptlang.org/docs/handbook/interfaces.html
[type aliases]: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases
[overloading functions]: https://www.typescriptlang.org/docs/handbook/functions.html#overloads
[mixins]: https://www.typescriptlang.org/docs/handbook/mixins.html
[decorators]: https://www.typescriptlang.org/docs/handbook/decorators.html
[async/await]: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await
[any]: https://www.typescriptlang.org/docs/handbook/basic-types.html#any
[type guards]: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types
[type assertions]: https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions
[union types]: https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types
[lookup types]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#keyof-and-lookup-types
[mapped types]: https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types
[const assertions]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
[enums]: https://www.typescriptlang.org/docs/handbook/enums.html

0 comments on commit e6e46a2

Please sign in to comment.