From 7ab6da24356b84672010f6ae2b8e1c920ac5ccad Mon Sep 17 00:00:00 2001 From: Josh Black Date: Thu, 20 Jun 2024 13:01:24 -0500 Subject: [PATCH] docs(versioning): update guide with changes to event handlers --- contributor-docs/versioning.md | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/contributor-docs/versioning.md b/contributor-docs/versioning.md index a96ae1cbf89..744f1c9e89f 100644 --- a/contributor-docs/versioning.md +++ b/contributor-docs/versioning.md @@ -16,6 +16,7 @@ - [A component includes a landmark role](#a-component-includes-a-landmark-role) - [A component no longer includes a landmark role](#a-component-no-longer-includes-a-landmark-role) - [The element onto which props are spread is changed](#the-element-onto-which-props-are-spread-is-changed) + - [The element type in an event handler becomes broader](#the-element-type-in-an-event-handler-becomes-broader) @@ -56,6 +57,7 @@ For a full list of releases, visit our [releases](https://github.com/primer/reac | | A prop is deprecated | `minor` | | | A prop is removed | `major` | | | [The element onto which props are spread is changed](#the-element-onto-which-props-are-spread-is-changed) | potentially `major` | +| | [The element type in an event handler becomes broader](#the-element-type-in-an-event-handler-becomes-broader) | `major` | | Package | A dependency is added | `minor` | | | A dependency is removed and it does not affect the public API of the package | `minor` | | | A dependency is removed and it does affect the public API of the package | `major` | @@ -246,3 +248,65 @@ function Component(props: Props) { ``` + +### The element type in an event handler becomes broader + +semver bump: **major** + +This is a breaking change due to how extracted event handlers need to be typed. +Consider the following example: + +```tsx +function ExampleComponent() { + return ( + { + // + }} + /> + ) +} +``` + +When the `onSelect` handler is provided inline, the type is inferred and does +not need to be explicitly defined. However, when this handler is pulled out then +the type is defined: + +```tsx +function ExampleComponent() { + function onSelect(event: React.MouseEvent) { + // + } + + return +} +``` + +This situation is what will cause a breaking change if we change the base +element type of this event handler. For example, if we update the props of +`Item` to be the following: + +```diff +interface ItemProps { +- onSelect(event: React.MouseEvent): void; ++ onSelect(event: React.MouseEvent): void; +} +``` + +Then the downstream consumers that have typed `onSelect` will now have a +TypeScript error since `HTMLDivElement` does not fully overlap with `HTMLElement`. + +When choosing to expose event handler types, consider what the minimum type is +that will satisfy the requirements by callers. Additionally, when typing +handlers of components it is recommended to use the type from the component +props directly. For example: + +```tsx +function ExampleComponent() { + const onSelect: ItemProps['onSelect'] = event => { + // + } + + return +} +```