Skip to content

chore: Explicit module boundary types #7764

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

Merged
merged 20 commits into from
Mar 13, 2025

Conversation

snowystinger
Copy link
Member

@snowystinger snowystinger commented Feb 12, 2025

Closes

See https://typescript-eslint.io/rules/explicit-module-boundary-types/

Update: Ended up doing all of it.

Starts us on the road of explicit return types for functions. This has the end benefits of speeding up our typescript and making it easier and faster to ts diff.
Also, tsdiff will be more accurate, as we can see below. We had a bunch of functions that it thought would return void when that was not the case.

We can start with just the function that we export (there are some caveats as, "is this function exported" is actually pretty difficult to answer, see typescript-eslint/typescript-eslint#65)

We can add to the globs that determine what files this rule runs on to do it incrementally. I've started us here by doing all of react-aria-components, internationalized, and react-stately.

Once this is complete, we can move on to various levels of permission on https://typescript-eslint.io/rules/explicit-function-return-type/ which would apply the rule to non-exported functions as well.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@rspbot
Copy link

rspbot commented Feb 12, 2025

@rspbot
Copy link

rspbot commented Feb 12, 2025

# Conflicts:
#	packages/@react-stately/virtualizer/src/Layout.ts
#	packages/react-aria-components/src/Virtualizer.tsx
@rspbot
Copy link

rspbot commented Feb 20, 2025

@rspbot
Copy link

rspbot commented Feb 20, 2025

# Conflicts:
#	packages/@react-aria/collections/src/Hidden.tsx
#	packages/@react-aria/tree/src/useTree.ts
#	packages/@react-spectrum/s2/src/Picker.tsx
#	packages/@react-spectrum/s2/src/TableView.tsx
#	packages/@react-spectrum/s2/src/TreeView.tsx
#	packages/@react-spectrum/tree/src/TreeView.tsx
#	packages/@react-stately/layout/src/GridLayout.ts
#	packages/@react-stately/toast/src/useToastState.ts
#	packages/react-aria-components/src/Autocomplete.tsx
#	packages/react-aria-components/src/Virtualizer.tsx
@rspbot
Copy link

rspbot commented Feb 26, 2025

# Conflicts:
#	packages/@react-aria/datepicker/src/useDatePickerGroup.ts
#	packages/@react-spectrum/s2/src/TreeView.tsx
#	packages/@react-spectrum/tree/src/TreeView.tsx
@rspbot
Copy link

rspbot commented Mar 6, 2025

@snowystinger snowystinger changed the title chore: Start incremental explicit module boundary types chore: Explicit module boundary types Mar 6, 2025
@rspbot
Copy link

rspbot commented Mar 11, 2025

@rspbot
Copy link

rspbot commented Mar 11, 2025

# Conflicts:
#	packages/@react-aria/collections/src/Document.ts
@rspbot
Copy link

rspbot commented Mar 12, 2025

@rspbot
Copy link

rspbot commented Mar 12, 2025

## API Changes

react-aria-components

/react-aria-components:ColorWheelTrack

 ColorWheelTrack {
   className?: string | ((ColorWheelTrackRenderProps & {
     defaultClassName: string | undefined
 })) => string
+  id?: string
   style?: CSSProperties | ((ColorWheelTrackRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
 }

/react-aria-components:OverlayArrow

 OverlayArrow extends HTMLAttributes {
   children?: ReactNode | ((OverlayArrowRenderProps & {
     defaultChildren: ReactNode | undefined
 })) => ReactNode
   className?: string | ((OverlayArrowRenderProps & {
     defaultClassName: string | undefined
 })) => string
+  id?: string
   style?: CSSProperties | ((OverlayArrowRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
 }

/react-aria-components:TableLayout

 TableLayout <O extends TableLayoutProps = TableLayoutProps, T> {
   constructor: (ListLayoutOptions) => void
-  getContentSize: () => void
+  getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect) => void
+  getLayoutInfo: (Key) => LayoutInfo | null
+  getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (TableLayoutProps, TableLayoutProps) => boolean
   update: (InvalidationContext<TableLayoutProps>) => void
-  updateItemSize: (Key, Size) => void
-  useLayoutOptions: () => void
+  updateItemSize: (Key, Size) => boolean
+  useLayoutOptions: () => TableLayoutProps
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:UNSTABLE_ToastQueue

 UNSTABLE_ToastQueue <T> {
-  add: (T, ToastOptions) => void
+  add: (T, ToastOptions) => string
   close: (string) => void
   constructor: (ToastStateProps) => void
   pauseAll: () => void
   resumeAll: () => void
-  subscribe: (() => void) => void
+  subscribe: (() => void) => () => boolean
   visibleToasts: Array<QueuedToast<T>>
 }

/react-aria-components:ListLayout

 ListLayout <O extends ListLayoutOptions = ListLayoutOptions, T> {
   constructor: (ListLayoutOptions) => void
-  getContentSize: () => void
+  getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect) => void
+  getLayoutInfo: (Key) => LayoutInfo | null
+  getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (ListLayoutOptions, ListLayoutOptions) => boolean
   update: (InvalidationContext<ListLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:GridLayout

 GridLayout <O extends GridLayoutOptions = GridLayoutOptions, T> {
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (GridLayoutOptions, GridLayoutOptions) => boolean
   update: (InvalidationContext<GridLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:WaterfallLayout

 WaterfallLayout <O extends WaterfallLayoutOptions = WaterfallLayoutOptions, T extends {}> {
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getKeyLeftOf: (Key) => Key | null
   getKeyRange: (Key, Key) => Array<Key>
   getKeyRightOf: (Key) => Key | null
   getLayoutInfo: (Key) => LayoutInfo
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (WaterfallLayoutOptions, WaterfallLayoutOptions) => boolean
   update: (InvalidationContext<WaterfallLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:Size

 Size {
-  area: any
+  area: number
   constructor: (any, any) => void
   copy: () => Size
   equals: (Size) => boolean
   height: number
 }

/react-aria-components:Rect

 Rect {
   area: number
   bottomLeft: Point
   bottomRight: Point
   constructor: (any, any, any, any) => void
   containsPoint: (Point) => boolean
   containsRect: (Rect) => boolean
   copy: () => Rect
-  equals: (Rect) => void
+  equals: (Rect) => boolean
   getCornerInRect: (Rect) => RectCorner | null
   height: number
   intersection: (Rect) => Rect
   intersects: (Rect) => boolean
   maxX: number
   maxY: number
-  pointEquals: (Point | Rect) => void
-  sizeEquals: (Size | Rect) => void
+  pointEquals: (Point | Rect) => boolean
+  sizeEquals: (Size | Rect) => boolean
   topLeft: Point
   topRight: Point
-  union: (Rect) => void
+  union: (Rect) => Rect
   width: number
   x: number
   y: number
 }

/react-aria-components:ColorWheelTrackProps

 ColorWheelTrackProps {
   className?: string | ((ColorWheelTrackRenderProps & {
     defaultClassName: string | undefined
 })) => string
+  id?: string
   style?: CSSProperties | ((ColorWheelTrackRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
 }

/react-aria-components:OverlayArrowProps

 OverlayArrowProps {
   children?: ReactNode | ((OverlayArrowRenderProps & {
     defaultChildren: ReactNode | undefined
 })) => ReactNode
   className?: string | ((OverlayArrowRenderProps & {
     defaultClassName: string | undefined
 })) => string
+  id?: string
   style?: CSSProperties | ((OverlayArrowRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
 }

@internationalized/date

/@internationalized/date:Time

 Time {
-  add: (TimeDuration) => void
-  compare: (AnyTime) => void
+  add: (TimeDuration) => Time
+  compare: (AnyTime) => number
   constructor: (number, number, number, number) => void
   copy: () => Time
-  cycle: (TimeField, number, CycleTimeOptions) => void
+  cycle: (TimeField, number, CycleTimeOptions) => Time
   hour: number
   millisecond: number
   minute: number
   second: number
-  set: (TimeFields) => void
-  subtract: (TimeDuration) => void
-  toString: () => void
+  set: (TimeFields) => Time
+  subtract: (TimeDuration) => Time
+  toString: () => string
   UNKNOWN: any
 }

/@internationalized/date:ZonedDateTime

 ZonedDateTime {
-  add: (DateTimeDuration) => void
+  add: (DateTimeDuration) => ZonedDateTime
   calendar: Calendar
-  compare: (CalendarDate | CalendarDateTime | ZonedDateTime) => void
+  compare: (CalendarDate | CalendarDateTime | ZonedDateTime) => number
   constructor: (Array<any>) => void
   copy: () => ZonedDateTime
-  cycle: (DateField | TimeField, number, CycleTimeOptions) => void
+  cycle: (DateField | TimeField, number, CycleTimeOptions) => ZonedDateTime
   day: number
   era: string
   hour: number
   millisecond: number
   minute: number
   month: number
   offset: number
   second: number
-  set: ((DateFields & TimeFields), Disambiguation) => void
-  subtract: (DateTimeDuration) => void
+  set: ((DateFields & TimeFields), Disambiguation) => ZonedDateTime
+  subtract: (DateTimeDuration) => ZonedDateTime
   timeZone: string
-  toAbsoluteString: () => void
-  toDate: () => void
-  toString: () => void
+  toAbsoluteString: () => string
+  toDate: () => Date
+  toString: () => string
   UNKNOWN: any
   year: number
 }

/@internationalized/date:GregorianCalendar

 GregorianCalendar {
   balanceDate: (Mutable<AnyCalendarDate>) => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
 }

/@internationalized/date:JapaneseCalendar

 JapaneseCalendar {
   balanceDate: (Mutable<AnyCalendarDate>) => void
   constrainDate: (Mutable<AnyCalendarDate>) => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMinimumDayInMonth: (AnyCalendarDate) => number
   getMinimumMonthInYear: (AnyCalendarDate) => number
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:BuddhistCalendar

 BuddhistCalendar {
   balanceDate: () => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:TaiwanCalendar

 TaiwanCalendar {
   balanceDate: (Mutable<AnyCalendarDate>) => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:PersianCalendar

 PersianCalendar {
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: () => number
   identifier: any
   toJulianDay: (AnyCalendarDate) => number

/@internationalized/date:IndianCalendar

 IndianCalendar {
   balanceDate: () => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: () => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:IslamicCivilCalendar

 IslamicCivilCalendar {
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: () => number
   identifier: any
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:IslamicTabularCalendar

 IslamicTabularCalendar {
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: () => number
   identifier: any
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:IslamicUmalquraCalendar

 IslamicUmalquraCalendar {
   constructor: () => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: () => number
   identifier: any
   toJulianDay: (AnyCalendarDate) => number

/@internationalized/date:HebrewCalendar

 HebrewCalendar {
   balanceYearMonth: (Mutable<AnyCalendarDate>, AnyCalendarDate) => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: (AnyCalendarDate) => number
   getYearsInEra: () => number
   identifier: any
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:EthiopicCalendar

 EthiopicCalendar {
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:EthiopicAmeteAlemCalendar

 EthiopicAmeteAlemCalendar {
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: () => number
   identifier: any
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

/@internationalized/date:CopticCalendar

 CopticCalendar {
   balanceDate: (Mutable<AnyCalendarDate>) => void
   fromJulianDay: (number) => CalendarDate
   getDaysInMonth: (AnyCalendarDate) => number
   getDaysInYear: (AnyCalendarDate) => number
-  getEras: () => void
+  getEras: () => Array<string>
   getMonthsInYear: () => number
   getYearsInEra: (AnyCalendarDate) => number
   identifier: any
   isInverseEra: (AnyCalendarDate) => boolean
-  toJulianDay: (AnyCalendarDate) => void
+  toJulianDay: (AnyCalendarDate) => number
 }

@internationalized/message

/@internationalized/message:MessageDictionary

 MessageDictionary {
   constructor: (LocalizedStrings, string) => void
-  getStringForLocale: (string, string) => void
+  getStringForLocale: (string, string) => string
 }

/@internationalized/message:MessageFormatter

 MessageFormatter {
   constructor: (string, MessageDictionary) => void
-  format: (string, Record<string, PrimitiveType | T | FormatXMLElementFn<T, string | T | Array<string | T>>> | undefined) => void
+  format: (string, Record<string, PrimitiveType | T | FormatXMLElementFn<T, string | T | Array<string | T>>> | undefined) => string | T | Array<string | T>
 }

@react-aria/collections

/@react-aria/collections:BaseCollection

 BaseCollection <T> {
   UNSTABLE_filter: ((string) => boolean) => BaseCollection<T>
   addNode: (CollectionNode<T>) => void
   at: () => Node<T>
   clone: () => this
   commit: (Key | null, Key | null, any) => void
   getChildren: (Key) => Iterable<Node<T>>
-  getFirstKey: () => void
+  getFirstKey: () => Key | null
   getItem: (Key) => Node<T> | null
-  getKeyAfter: (Key) => void
-  getKeyBefore: (Key) => void
-  getKeys: () => void
-  getLastKey: () => void
+  getKeyAfter: (Key) => Key | null
+  getKeyBefore: (Key) => Key | null
+  getKeys: () => IterableIterator<Key>
+  getLastKey: () => Key | null
   removeNode: (Key) => void
-  size: any
-  undefined: () => void
+  size: number
+  undefined: () => IterableIterator<Node<T>>
 }

@react-aria/grid

/@react-aria/grid:GridKeyboardDelegate

 GridKeyboardDelegate <C extends GridCollection<T>, T> {
   collection: GridCollection<T>
   constructor: (GridKeyboardDelegateOptions<GridCollection<T>>) => void
-  getFirstKey: (Key, boolean) => void
-  getKeyAbove: (Key) => void
-  getKeyBelow: (Key) => void
-  getKeyForSearch: (string, Key) => void
-  getKeyLeftOf: (Key) => void
-  getKeyPageAbove: (Key) => void
-  getKeyPageBelow: (Key) => void
-  getKeyRightOf: (Key) => void
-  getLastKey: (Key, boolean) => void
+  getFirstKey: (Key, boolean) => Key | null
+  getKeyAbove: (Key) => Key | null
+  getKeyBelow: (Key) => Key | null
+  getKeyForSearch: (string, Key) => Key | null
+  getKeyLeftOf: (Key) => Key | null
+  getKeyPageAbove: (Key) => Key | null
+  getKeyPageBelow: (Key) => Key | null
+  getKeyRightOf: (Key) => Key | null
+  getLastKey: (Key, boolean) => Key | null
 }

@react-aria/selection

/@react-aria/selection:ListKeyboardDelegate

 ListKeyboardDelegate <T> {
   constructor: (Array<any>) => void
-  getFirstKey: () => void
-  getKeyAbove: (Key) => void
-  getKeyBelow: (Key) => void
-  getKeyForSearch: (string, Key) => void
-  getKeyLeftOf: (Key) => void
-  getKeyPageAbove: (Key) => void
-  getKeyPageBelow: (Key) => void
-  getKeyRightOf: (Key) => void
-  getLastKey: () => void
-  getNextKey: (Key) => void
-  getPreviousKey: (Key) => void
+  getFirstKey: () => Key | null
+  getKeyAbove: (Key) => Key | null
+  getKeyBelow: (Key) => Key | null
+  getKeyForSearch: (string, Key) => Key | null
+  getKeyLeftOf: (Key) => Key | null
+  getKeyPageAbove: (Key) => Key | null
+  getKeyPageBelow: (Key) => Key | null
+  getKeyRightOf: (Key) => Key | null
+  getLastKey: () => Key | null
+  getNextKey: (Key) => Key | null
+  getPreviousKey: (Key) => Key | null
 }

@react-aria/utils

/@react-aria/utils:getEventTarget

-getEventTarget {
+getEventTarget <T extends Event> {
-  event: any
+  event: T
   returnVal: undefined
 }

/@react-aria/utils:getOffset

 getOffset {
-  element: any
-  reverse: any
-  orientation: any
+  element: HTMLElement
+  reverse?: boolean
+  orientation: Orientation
   returnVal: undefined
 }

@react-spectrum/card

/@react-spectrum/card:GalleryLayout

 GalleryLayout <T> {
-  _distributeWidths: (any) => void
-  _findClosest: (Rect, Rect) => void
-  _findClosestLayoutInfo: (Rect, Rect) => void
+  _distributeWidths: (Array<number>) => boolean
+  _findClosest: (Rect, Rect) => LayoutInfo | null
+  _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildCollection: () => void
   collection: GridCollection<T>
   constructor: (GalleryLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
-  getContentSize: () => void
+  getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getFirstKey: () => void
-  getKeyAbove: (Key) => void
-  getKeyBelow: (Key) => void
-  getKeyForSearch: (string, Key) => void
-  getKeyLeftOf: (Key) => void
-  getKeyPageAbove: (Key) => void
-  getKeyPageBelow: (Key) => void
-  getKeyRightOf: (Key) => void
-  getLastKey: () => void
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect, any) => void
+  getFirstKey: () => Node<T> | undefined
+  getKeyAbove: (Key) => Node<T> | undefined
+  getKeyBelow: (Key) => Node<T> | undefined
+  getKeyForSearch: (string, Key) => Node<T> | undefined | null
+  getKeyLeftOf: (Key) => Node<T> | undefined
+  getKeyPageAbove: (Key) => Node<T> | undefined
+  getKeyPageBelow: (Key) => Node<T> | undefined
+  getKeyRightOf: (Key) => Node<T> | undefined
+  getLastKey: () => Node<T> | undefined
+  getLayoutInfo: (Key) => LayoutInfo
+  getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
-  isVisible: (LayoutInfo, Rect, boolean) => void
+  isVisible: (LayoutInfo, Rect, boolean) => boolean
   itemPadding: number
-  layoutType: any
+  layoutType: string
   margin: number
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-spectrum/card:GridLayout

 GridLayout <T> {
-  _findClosest: (Rect, Rect) => void
-  _findClosestLayoutInfo: (Rect, Rect) => void
+  _findClosest: (Rect, Rect) => LayoutInfo | null
+  _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildChild: (Node<T>, number, number) => LayoutInfo
   buildCollection: () => void
   cardOrientation: Orientation
   collection: GridCollection<T>
   constructor: (GridLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
-  getContentSize: () => void
+  getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getFirstKey: () => void
-  getIndexAtPoint: (any, any, any) => void
-  getKeyAbove: (Key) => void
-  getKeyBelow: (Key) => void
-  getKeyForSearch: (string, Key) => void
-  getKeyLeftOf: (Key) => void
-  getKeyPageAbove: (Key) => void
-  getKeyPageBelow: (Key) => void
-  getKeyRightOf: (Key) => void
-  getLastKey: () => void
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect, any) => void
+  getFirstKey: () => Node<T> | undefined
+  getIndexAtPoint: (number, number, any) => number
+  getKeyAbove: (Key) => Node<T> | undefined | null
+  getKeyBelow: (Key) => Node<T> | undefined | null
+  getKeyForSearch: (string, Key) => Node<T> | undefined | null
+  getKeyLeftOf: (Key) => Node<T> | undefined
+  getKeyPageAbove: (Key) => Node<T> | undefined
+  getKeyPageBelow: (Key) => Node<T> | undefined
+  getKeyRightOf: (Key) => Node<T> | undefined
+  getLastKey: () => Node<T> | undefined
+  getLayoutInfo: (Key) => LayoutInfo
+  getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
-  isVisible: (LayoutInfo, Rect, boolean) => void
+  isVisible: (LayoutInfo, Rect, boolean) => boolean
   itemPadding: number
-  layoutType: any
+  layoutType: string
   margin: number
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-spectrum/card:WaterfallLayout

 WaterfallLayout <T> {
-  _findClosest: (Rect, Rect) => void
-  _findClosestLayoutInfo: (Rect, Rect) => void
+  _findClosest: (Rect, Rect) => LayoutInfo | null
+  _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildCollection: (InvalidationContext) => void
   collection: GridCollection<T>
   constructor: (WaterfallLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
-  getClosestLeft: (Key) => void
-  getClosestRight: (Key) => void
-  getContentSize: () => void
+  getClosestLeft: (Key) => Node<T> | undefined
+  getClosestRight: (Key) => Node<T> | undefined
+  getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getFirstKey: () => void
-  getKeyAbove: (Key) => void
-  getKeyBelow: (Key) => void
-  getKeyForSearch: (string, Key) => void
-  getKeyLeftOf: (Key) => void
-  getKeyPageAbove: (Key) => void
-  getKeyPageBelow: (Key) => void
-  getKeyRightOf: (Key) => void
-  getLastKey: () => void
-  getLayoutInfo: (Key) => void
-  getNextColumnIndex: (any) => void
-  getVisibleLayoutInfos: (Rect, any) => void
+  getFirstKey: () => Node<T> | undefined
+  getKeyAbove: (Key) => Node<T> | undefined
+  getKeyBelow: (Key) => Node<T> | undefined
+  getKeyForSearch: (string, Key) => Node<T> | undefined | null
+  getKeyLeftOf: (Key) => Node<T> | undefined
+  getKeyPageAbove: (Key) => Node<T> | undefined
+  getKeyPageBelow: (Key) => Node<T> | undefined
+  getKeyRightOf: (Key) => Node<T> | undefined
+  getLastKey: () => Node<T> | undefined
+  getLayoutInfo: (Key) => LayoutInfo
+  getNextColumnIndex: (Array<number>) => number
+  getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
-  isVisible: (LayoutInfo, Rect, boolean) => void
-  layoutType: any
+  isVisible: (LayoutInfo, Rect, boolean) => boolean
+  layoutType: string
   margin: number
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<CardViewLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => number
   virtualizer: Virtualizer<{}, any> | null
 }

@react-spectrum/story-utils

/@react-spectrum/story-utils:ErrorBoundary

 ErrorBoundary {
-  constructor: (any) => void
-  getDerivedStateFromError: () => void
-  render: () => void
+  constructor: ({
+    message: string
+  children: ReactNode
+}) => void
+  getDerivedStateFromError: () => {
+    hasError: boolean
 }
+  render: () => ReactNode
+}

@react-spectrum/utils

/@react-spectrum/utils:passthroughStyle

-passthroughStyle {
+passthroughStyle <T> {
-  value: any
+  value: T
   returnVal: undefined
 }

/@react-spectrum/utils:cssModuleToSlots

 cssModuleToSlots {
-  cssModule: any
+  cssModule: {
+    [cssmodule: string]: string
+}
   returnVal: undefined
 }

/@react-spectrum/utils:SlotProvider

 SlotProvider {
-
+  children?: ReactNode
+  slots?: {
+    [slot: string]: {}
 }
+}

/@react-spectrum/utils:ClearSlots

 ClearSlots {
-
+  children?: ReactNode
 }

@react-stately/collections

/@react-stately/collections:CollectionBuilder

 CollectionBuilder <T extends {}> {
-  build: (Partial<CollectionBase<{}>>, unknown) => void
+  build: (Partial<CollectionBase<{}>>, unknown) => Iterable<Node<{}>>
 }

@react-stately/datepicker

/@react-stately/datepicker:FormatterOptions

+FormatterOptions {
+  granularity?: DatePickerProps<any>['granularity']
+  hideTimeZone?: boolean
+  hourCycle?: number | number
+  maxGranularity?: 'year' | 'month' | DatePickerProps<any>['granularity']
+  shouldForceLeadingZeros?: boolean
+  showEra?: boolean
+  timeZone?: string
+}

@react-stately/grid

/@react-stately/grid:GridCollection

 GridCollection <T> {
-  at: (number) => void
+  at: (number) => GridNode<T> | null
   columnCount: number
   constructor: (GridCollectionOptions<T>) => void
   getChildren: (Key) => Iterable<GridNode<T>>
   getFirstKey: () => Key | null
-  getItem: (Key) => void
-  getKeyAfter: (Key) => void
-  getKeyBefore: (Key) => void
-  getKeys: () => void
+  getItem: (Key) => GridNode<T> | null
+  getKeyAfter: (Key) => Key | null
+  getKeyBefore: (Key) => Key | null
+  getKeys: () => IterableIterator<Key>
   getLastKey: () => Key | null
   keyMap: Map<Key, GridNode<T>>
   rows: Array<GridNode<T>>
-  size: any
-  undefined: () => void
+  size: number
+  undefined: () => IterableIterator<GridNode<T>>
 }

@react-stately/layout

/@react-stately/layout:GridLayout

 GridLayout <O extends GridLayoutOptions = GridLayoutOptions, T> {
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (GridLayoutOptions, GridLayoutOptions) => boolean
   update: (InvalidationContext<GridLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:ListLayout

 ListLayout <O extends ListLayoutOptions = ListLayoutOptions, T> {
   constructor: (ListLayoutOptions) => void
-  getContentSize: () => void
+  getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect) => void
+  getLayoutInfo: (Key) => LayoutInfo | null
+  getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (ListLayoutOptions, ListLayoutOptions) => boolean
   update: (InvalidationContext<ListLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:TableLayout

 TableLayout <O extends TableLayoutProps = TableLayoutProps, T> {
   constructor: (ListLayoutOptions) => void
-  getContentSize: () => void
+  getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
-  getLayoutInfo: (Key) => void
-  getVisibleLayoutInfos: (Rect) => void
+  getLayoutInfo: (Key) => LayoutInfo | null
+  getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (TableLayoutProps, TableLayoutProps) => boolean
   update: (InvalidationContext<TableLayoutProps>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:WaterfallLayout

 WaterfallLayout <O extends WaterfallLayoutOptions = WaterfallLayoutOptions, T extends {}> {
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getKeyLeftOf: (Key) => Key | null
   getKeyRange: (Key, Key) => Array<Key>
   getKeyRightOf: (Key) => Key | null
   getLayoutInfo: (Key) => LayoutInfo
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (WaterfallLayoutOptions, WaterfallLayoutOptions) => boolean
   update: (InvalidationContext<WaterfallLayoutOptions>) => void
-  updateItemSize: (Key, Size) => void
+  updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

@react-stately/list

/@react-stately/list:ListCollection

 ListCollection <T> {
-  at: (number) => void
+  at: (number) => Node<T> | null
   constructor: (Iterable<Node<T>>) => void
   getChildren: (Key) => Iterable<Node<T>>
-  getFirstKey: () => void
-  getItem: (Key) => void
-  getKeyAfter: (Key) => void
-  getKeyBefore: (Key) => void
-  getKeys: () => void
-  getLastKey: () => void
-  size: any
-  undefined: () => void
+  getFirstKey: () => Key | null
+  getItem: (Key) => Node<T> | null
+  getKeyAfter: (Key) => Key | null
+  getKeyBefore: (Key) => Key | null
+  getKeys: () => IterableIterator<Key>
+  getLastKey: () => Key | null
+  size: number
+  undefined: () => IterableIterator<Node<T>>
 }

@react-stately/selection

/@react-stately/selection:SelectionManager

 SelectionManager {
-  canSelectItem: (Key) => void
+  canSelectItem: (Key) => boolean
   childFocusStrategy: FocusStrategy | null
   clearSelection: () => void
   collection: Collection<Node<unknown>>
   constructor: (Collection<Node<unknown>>, MultipleSelectionState, SelectionManagerOptions) => void
   disabledBehavior: DisabledBehavior
   disabledKeys: Set<Key>
   disallowEmptySelection: boolean
   extendSelection: (Key) => void
   firstSelectedKey: Key | null
   focusedKey: Key | null
-  getItemProps: (Key) => void
-  isDisabled: (Key) => void
+  getItemProps: (Key) => any
+  isDisabled: (Key) => boolean
   isEmpty: boolean
   isFocused: boolean
-  isLink: (Key) => void
+  isLink: (Key) => boolean
   isSelectAll: boolean
-  isSelected: (Key) => void
-  isSelectionEqual: (Set<Key>) => void
+  isSelected: (Key) => boolean
+  isSelectionEqual: (Set<Key>) => boolean
   lastSelectedKey: Key | null
   rawSelection: Selection
   replaceSelection: (Key) => void
   select: (Key, PressEvent | LongPressEvent | PointerEvent) => void
   selectAll: () => void
   selectedKeys: Set<Key>
   selectionBehavior: SelectionBehavior
   selectionMode: SelectionMode
   setFocused: (boolean) => void
   setFocusedKey: (Key | null, FocusStrategy) => void
   setSelectedKeys: (Iterable<Key>) => void
   setSelectionBehavior: (SelectionBehavior) => void
   toggleSelectAll: () => void
   toggleSelection: (Key) => void
-  withCollection: (Collection<Node<unknown>>) => void
+  withCollection: (Collection<Node<unknown>>) => SelectionManager
 }

@react-stately/table

/@react-stately/table:TableCollection

 TableCollection <T> {
   _size: number
-  at: (number) => void
+  at: (number) => GridNode<T> | null
   body: GridNode<T>
   columnCount: number
   columns: Array<GridNode<T>>
   constructor: (Iterable<GridNode<T>>, TableCollection<T> | null, GridCollectionOptions) => void
   getChildren: (Key) => Iterable<GridNode<T>>
-  getFirstKey: () => void
-  getItem: (Key) => void
-  getKeyAfter: (Key) => void
-  getKeyBefore: (Key) => void
-  getKeys: () => void
-  getLastKey: () => void
+  getFirstKey: () => Key | null
+  getItem: (Key) => GridNode<T> | null
+  getKeyAfter: (Key) => Key | null
+  getKeyBefore: (Key) => Key | null
+  getKeys: () => IterableIterator<Key>
+  getLastKey: () => Key | null
   getTextValue: (Key) => string
   headerRows: Array<GridNode<T>>
   keyMap: Map<Key, GridNode<T>>
   rowHeaderColumnKeys: Set<Key>
   rows: Array<GridNode<T>>
-  size: any
-  undefined: () => void
+  size: number
+  undefined: () => IterableIterator<GridNode<T>>
 }

/@react-stately/table:TableColumnLayout

 TableColumnLayout <T> {
-  buildColumnWidths: (number, TableCollection<T>, Map<Key, ColumnSize>) => void
+  buildColumnWidths: (number, TableCollection<T>, Map<Key, ColumnSize>) => Map<Key, number>
   columnMaxWidths: Map<Key, number>
   columnMinWidths: Map<Key, number>
   columnWidths: Map<Key, number>
   constructor: (TableColumnLayoutOptions<T>) => void
   getColumnMinWidth: (Key) => number
   getColumnWidth: (Key) => number
   getDefaultMinWidth: (GridNode<T>) => ColumnSize | null | undefined
   getDefaultWidth: (GridNode<T>) => ColumnSize | null | undefined
   getInitialUncontrolledWidths: (Map<Key, GridNode<T>>) => Map<Key, ColumnSize>
   recombineColumns: (Array<GridNode<T>>, Map<Key, ColumnSize>, Map<Key, GridNode<T>>, Map<Key, GridNode<T>>) => Map<Key, ColumnSize>
   resizeColumnWidth: (TableCollection<T>, Map<Key, ColumnSize>, Key, number) => Map<Key, ColumnSize>
   splitColumnsIntoControlledAndUncontrolled: (Array<GridNode<T>>) => [Map<Key, GridNode<T>>, Map<Key, GridNode<T>>]
 }

@react-stately/toast

/@react-stately/toast:ToastQueue

 ToastQueue <T> {
-  add: (T, ToastOptions) => void
+  add: (T, ToastOptions) => string
   close: (string) => void
   constructor: (ToastStateProps) => void
   pauseAll: () => void
   resumeAll: () => void
-  subscribe: (() => void) => void
+  subscribe: (() => void) => () => boolean
   visibleToasts: Array<QueuedToast<T>>
 }

@react-stately/tree

/@react-stately/tree:TreeCollection

 TreeCollection <T> {
-  at: (number) => void
+  at: (number) => Node<T> | null
   constructor: (Iterable<Node<T>>, {
     expandedKeys?: Set<Key>
 }) => void
-  getFirstKey: () => void
-  getItem: (Key) => void
-  getKeyAfter: (Key) => void
-  getKeyBefore: (Key) => void
-  getKeys: () => void
-  getLastKey: () => void
-  size: any
-  undefined: () => void
+  getFirstKey: () => Key | null
+  getItem: (Key) => Node<T> | null
+  getKeyAfter: (Key) => Key | null
+  getKeyBefore: (Key) => Key | null
+  getKeys: () => IterableIterator<Key>
+  getLastKey: () => Key | null
+  size: number
+  undefined: () => IterableIterator<Node<T>>
 }

@react-stately/virtualizer

/@react-stately/virtualizer:Rect

 Rect {
   area: number
   bottomLeft: Point
   bottomRight: Point
   constructor: (any, any, any, any) => void
   containsPoint: (Point) => boolean
   containsRect: (Rect) => boolean
   copy: () => Rect
-  equals: (Rect) => void
+  equals: (Rect) => boolean
   getCornerInRect: (Rect) => RectCorner | null
   height: number
   intersection: (Rect) => Rect
   intersects: (Rect) => boolean
   maxX: number
   maxY: number
-  pointEquals: (Point | Rect) => void
-  sizeEquals: (Size | Rect) => void
+  pointEquals: (Point | Rect) => boolean
+  sizeEquals: (Size | Rect) => boolean
   topLeft: Point
   topRight: Point
-  union: (Rect) => void
+  union: (Rect) => Rect
   width: number
   x: number
   y: number
 }

/@react-stately/virtualizer:Size

 Size {
-  area: any
+  area: number
   constructor: (any, any) => void
   copy: () => Size
   equals: (Size) => boolean
   height: number
 }

/@react-stately/virtualizer:ReusableView

 ReusableView <T extends {}, V> {
   children: Set<ChildView<{}, V>>
   constructor: (Virtualizer<{}, V>, string) => void
   content: {} | null
-  getReusableView: (string) => void
+  getReusableView: (string) => ChildView<{}, V>
   key: Key
   layoutInfo: LayoutInfo | null
   prepareForReuse: () => void
   rendered: V | null
   reuseChild: (ChildView<{}, V>) => void
   viewType: string
   virtualizer: Virtualizer<{}, V>
 }

hasAttribute(): void {}
setAttribute(): void {}
setAttributeNS(): void {}
removeAttribute(): void {}
Copy link
Member

Choose a reason for hiding this comment

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

ugh, do we really have to annotate functions that don't return anything?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried it with the typescript features on and the eslint rule off, these appear to be necessary.

Method must have an explicit return type annotation with --isolatedDeclarations.

@@ -38,7 +38,7 @@ interface DropTarget {
export function registerDropTarget(target: DropTarget) {
dropTargets.set(target.element, target);
dragSession?.updateValidDropTargets();
return () => {
return (): void => {
Copy link
Member

@devongovett devongovett Mar 12, 2025

Choose a reason for hiding this comment

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

oh this will be really annoying. Actually, why is this one needed? This function isn't exported. Shouldn't the return type really be on registerDropTarget?

Copy link
Member Author

@snowystinger snowystinger Mar 12, 2025

Choose a reason for hiding this comment

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

yes, it can go on either because --isolatedDeclarations will work if the return value is trivial to determine. I do not know exactly what constitutes trivial. But you can search this page fortrivial to see some explanations https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations

Likely the eslint rule is catching too many because it doesn't know what is trivial or not. The hard part of doing this as typescript first though is that it's all or nothing whereas I was able to focus on changes with the eslint error.

Copy link
Member

Choose a reason for hiding this comment

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

our docs generator will not work with this one though. It will need to be on the exported function.

Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

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

I guess. I don't really like the amount of annotations we have to write.

@snowystinger snowystinger added this pull request to the merge queue Mar 13, 2025
Merged via the queue into main with commit 83ab4ef Mar 13, 2025
30 checks passed
@snowystinger snowystinger deleted the incremental-function-return-types branch March 13, 2025 21:40
@@ -90,7 +90,7 @@ let activeScope: ScopeRef = null;
* management interface that can be used to move focus forward and back in response
* to user events.
*/
export function FocusScope(props: FocusScopeProps) {
export function FocusScope(props: FocusScopeProps): ReactNode {

Choose a reason for hiding this comment

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

I think this change breaks compatibility with React17 and TS 5.4.2

image

Copy link
Member Author

@snowystinger snowystinger May 10, 2025

Choose a reason for hiding this comment

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

Thanks, should be fixed by #8099
in addition it can be fixed by updated your version of TS and possibly types/react

Choose a reason for hiding this comment

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

Thanks @snowystinger

Choose a reason for hiding this comment

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

@snowystinger I've noticed this wasn't fixed in #8099, are there any plans to fix this before the next release?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for catching that, fixed here: #8256

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants