Skip to content
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

[base-controller] Fix single-letter type param names #2030

Merged
merged 3 commits into from
Nov 15, 2023

Conversation

MajorLift
Copy link
Contributor

@MajorLift MajorLift commented Nov 13, 2023

Explanation

Renames all single-letter type parameter names in base-controller to be more descriptive.

References

Changelog

@metamask/base-controller

  • CHANGED: Renamed all single-letter generic parameter names to be descriptive

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@MajorLift MajorLift changed the title [base-controller] Fix single-letter type param names [base-controller] Fix single-letter type param names Nov 13, 2023
@MajorLift MajorLift self-assigned this Nov 13, 2023
@MajorLift MajorLift changed the base branch from 231023-queued-allowed-actions to main November 13, 2023 20:55
@MajorLift MajorLift changed the base branch from main to 231023-queued-allowed-actions November 13, 2023 20:56
@MajorLift MajorLift marked this pull request as ready for review November 13, 2023 21:04
@MajorLift MajorLift requested a review from a team as a code owner November 13, 2023 21:04
Base automatically changed from 231023-queued-allowed-actions to main November 15, 2023 16:59
@MajorLift MajorLift requested a review from a team as a code owner November 15, 2023 16:59
MajorLift added a commit that referenced this pull request Nov 15, 2023
…r functions (#1890)

## Motivation

The `ControllerMessenger` pattern that is used in all of our controllers
currently relies on unsafe typing, which includes `any` usage. A more
rigorous overhaul of these definitions will help us implement features
with more type-safe and robust code.

## Explanation

### Main

- Removes all `any` usage from `Action`, `Event` typing in
`ControllerMessenger`.
- Types `Action['handler']` with correct universal supertype for
functions.
- Fixes `SelectorFunction`, `EventSubscriptionMap` typing that was
causing errors.
- Improves `BaseController` typing by defining `NamespacedName` type:
the narrowest supertype of all names defined within a given namespace.
- `BaseController` now expects a "getState" action type and
"stateChange" event type in all controllers.

### Auxiliary

- Improved typing for `deriveStateFromMetadata`
- ~Rename all single-letter type param names to be more descriptive.~
(moved here: #2030)

### Notes on the "universal function supertype"

#### A. `(...args: never[]) => unknown`

`Action['handler'] extends ActionConstraint['handler']`, and in general
`Subtype extends Supertype`. Therefore, in order to assign any function
to `Action['handler']` without restrictions, we need
`ActionConstraint['handler']` to be the widest possible function i.e.
the supertype of all functions.

To achieve this, the return type of this supertype function needs to be
`unknown` (universal supertype), and the parameters need to be `never`
(universal subtype). This is because in general `(x: SuperType) => T` is
a *subtype* of `(x: SubType) => T`. So the params need to be the
narrowest type (i.e. `never`) for the function type to be widened into
the universal function supertype.

- There's an example of this in the [TypeScript
docs](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types).
- And here's a more detailed [reddit
comment](https://www.reddit.com/r/typescript/comments/muyl55/comment/gv9ndij/?utm_source=share&utm_medium=web2x&context=3)
on this topic.

#### B. `(...args: never) => unknown`

In general, array types of arbitrary length are not assignable to tuple
types that have fixed types designated to some or all of its index
positions (the array is wider than the tuple since it has less
constraints).

This means that there's a whole subcategory of functions that `(...args:
never[]) => unknown` doesn't cover: functions that have a finite number
of parameters that are strictly ordered and typed, making their spread
argument list evaluate as a fixed-length or variadic **tuple** type,
instead of a freely expandable (or contractable) **array** type.

That is, `(...args: never[]) => unknown` covers the cases where all of
the params can be typed together as a group e.g. `(...args: (string |
number)[]) => T`. But to cover cases like `(a: string, b: number,
...rest: unknown[]) => T`, we need another top type with an even
narrower type for the params: `(...args: never) => unknown`.

#### C. `((...args: never) => unknown) | ((...args: never[]) =>
unknown)`

In short, the above represents the top type that includes both of these
function categories.

- `| never` in general is analogous to `+ 0`, so `(...args: (never[] |
never)) => unknown` doesn't work.
- `(...args: never) => unknown` doesn't work with the error message
`Type 'T[]' is not assignable to type 'never'`.

## References

- Closes #2026

## Changelog

### `@metamask/base-controller`
- **CHANGED**: `ActionConstraint['handler']` has been fixed to remove
`any` usage, and is now defined as the universal supertype of all
functions, meaning any function can be safely assigned to it, regardless
of argument types, number of arguments, or return value type.
- **CHANGED** : `ExtractActionParameters` and `ExtractActionResponse`
have also been fixed to remove `any` usage, and to use the new typing of
`ActionConstraint['handler']`.
- **CHANGED**: **BREAKING** Alters `SelectorFunction` type, replacing
its `Args` generic parameter with an event payload type that is defined
with a new required generic parameter `Event`.
- **ADDED**: Exports `NamespacedName` type, which is the narrowest
supertype of all names defined within a given namespace.

### `@metamask/rate-limit-controller`
- **CHANGED**: **BREAKING** `RateLimitedApi['method']` is now
constrained by the `ActionConstraint['handler']` type from the
`@metamask/base-controller` module.

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate

---------

Co-authored-by: Mark Stacey <[email protected]>
Co-authored-by: Elliot Winkler <[email protected]>
Gudahtt
Gudahtt previously approved these changes Nov 15, 2023
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@MajorLift MajorLift force-pushed the 231113-base-controller-rename-single-letter-params branch from 4a37f64 to 357cde9 Compare November 15, 2023 18:06
@MajorLift MajorLift merged commit 4e8558e into main Nov 15, 2023
128 checks passed
@MajorLift MajorLift deleted the 231113-base-controller-rename-single-letter-params branch November 15, 2023 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants