Skip to content

Commit

Permalink
docs: πŸ“„ Introduce conventions (#385)
Browse files Browse the repository at this point in the history
* docs: πŸ“„ Conventions

* docs: πŸ“„ add example for Strict* convention

* docs: πŸ“„ changeset
  • Loading branch information
Beraliv committed Apr 7, 2024
1 parent 8e625d9 commit d2dbcf9
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/hip-papayas-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ts-essentials": patch
---

Added `CONVENTIONS.md` for reliable, consistent and predictable development
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

All contributions to `ts-essentials` are welcomed.

Do you have idea for a new type? Please, first submit github issue (or send me PM) and describe your proposal.
Do you have idea for a new type? Please, first submit a GitHub issue (or send me PM) and describe your proposal.

## Conventions

To follow ts-essentials conventions, please check [CONVENTIONS.md](./CONVENTIONS.md). Anything missing or something is
unclear? Don't hesitate to suggest it in a GitHub issue and please don't forget to add the `convention` label.

## Adding new types

Expand Down
46 changes: 46 additions & 0 deletions CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Conventions

The conventions are integral part of the ts-essentials library codebase: they provide a consistent way of development
for both maintainers and engineers that use this library.

## Naming

Consistent naming improves readability and simplifies the maintainability.

Prefixes:

- `Any*` prefix is used for top types for specified subset of types, e.g.
[`AnyFunction<Args?, ReturnType?>`](./lib/any-function/) for any possible functions,
[`AnyArray<Type?>`](/lib/any-array) for any type of arrays, etc.
- ⚠️ [`NonEmptyArray<Type>`](/lib/non-empty-array) doesn't follow this rule and has to be renamed to
`AnyNonEmptyArray`
- `Deep*` prefix is used when the type changes are applied to the whole structure recursively.
- If you wonder why [`Buildable<Type>`](./lib/buildable/) doesn't include a prefix, it is because it doesn't have
direct recursive call
- `Is*` prefix is used when type expects to return `true` or `false`
- ⚠️ Some types don't follow this convention for performance reasons, e.g. [`IsTuple<Type>`](/lib/is-tuple)
- ⚠️ [`Exact<Type, Shape>`](/lib/exact) return `Type` or `never` and has to be updated to `IsExact` to match the name
of respective function called `isExact`
- `Mark*` prefix is used when the partial type changes are applied to a type, e.g. some properties are set to optional
in [`MarkOptional<Type, Keys>`](/lib/mark-optional)
- `Non*` prefix is used when type expects to return `Type` or `never` (although this is not strict)
- [`NonNever<Type>`](/lib/non-never) doesn't return `never` so has to be renamed to `OmitNeverProperties`
- `Strict*` prefix is used when the additional generic constraint is applied to a type parameter to constrain its usage,
e.g. [`StrictOmit<Type, Keys>`](/lib/strict-omit) adds an additional generic constraint for `Keys extends keyof Type`
so only existing keys within `Type` are passed to this utility type.
- ⚠️ Inevitably all `Strict*` types lack the support of generic types for the first type parameter `Type` because
generic constraints rely on a structure of `Type` which cannot be inferred at declaration. To mitigate it, please
use non-`Strict*` analogue of a utility type.

Body:

- `*Or*` is used for top types for 2 types, e.g. [`AsyncOrSync<Type>`](/lib/async-or-sync) for either asynchronous type
(i.e. `PromiseLike`) or a synchronous type.
- [`AsyncOrSyncType<Type>`](/lib/async-or-sync-type) is an exception because it serves to unwrap `Type` in
`AsyncOrSync<Type>`.

Suffices:

- `*Keys` suffix is used when the names of the properties (i.e. the keys) are returned or manipulated
- `*Properties` suffix is used when the values of the properties (or simply properties) are returned or manipulated
- [`NonNever<Type>`](/lib/non-never) updates properties so has to be renamed to `OmitNeverProperties`

0 comments on commit d2dbcf9

Please sign in to comment.