Address any types in List component (#10504)

This commit is contained in:
DS Boyce
2026-05-15 12:42:32 -07:00
committed by GitHub
parent cc7d8296f0
commit 5b7bc56a12
3 changed files with 66 additions and 51 deletions
-10
View File
@@ -659,16 +659,6 @@
"count": 2 "count": 2
} }
}, },
"src/view/com/util/List.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 2
}
},
"src/view/com/util/List.web.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 14
}
},
"src/view/com/util/MainScrollProvider.tsx": { "src/view/com/util/MainScrollProvider.tsx": {
"@typescript-eslint/no-explicit-any": { "@typescript-eslint/no-explicit-any": {
"count": 2 "count": 2
+3 -1
View File
@@ -18,6 +18,8 @@ import {IS_IOS} from '#/env'
import {FlatList_INTERNAL} from './Views' import {FlatList_INTERNAL} from './Views'
export type ListMethods = FlatList_INTERNAL export type ListMethods = FlatList_INTERNAL
// This is a generic type; we could update ~30 call sites but this approach is consistent with RN internals. -dsb
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ListProps<ItemT = any> = Omit< export type ListProps<ItemT = any> = Omit<
FlatListPropsWithLayout<ItemT>, FlatListPropsWithLayout<ItemT>,
| 'onMomentumScrollBegin' // Use ScrollContext instead. | 'onMomentumScrollBegin' // Use ScrollContext instead.
@@ -58,7 +60,7 @@ let List = forwardRef<ListMethods, ListProps>(
...props ...props
}, },
ref, ref,
): React.ReactElement<any> => { ): React.ReactElement => {
const isScrolledDown = useSharedValue(false) const isScrolledDown = useSharedValue(false)
const t = useTheme() const t = useTheme()
const dedupe = useDedupe(400) const dedupe = useDedupe(400)
+63 -40
View File
@@ -11,6 +11,7 @@ import {
} from 'react' } from 'react'
import { import {
type FlatListProps, type FlatListProps,
type ListRenderItemInfo,
StyleSheet, StyleSheet,
View, View,
type ViewProps, type ViewProps,
@@ -23,7 +24,11 @@ import {useScrollHandlers} from '#/lib/ScrollContext'
import {addStyle} from '#/lib/styles' import {addStyle} from '#/lib/styles'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
export type ListMethods = any // TODO: Better types. export type ListMethods = {
scrollToTop: () => void
scrollToOffset: (options: {animated: boolean; offset: number}) => void
scrollToEnd: (options?: {animated?: boolean}) => void
}
export type ListProps<ItemT> = Omit< export type ListProps<ItemT> = Omit<
FlatListProps<ItemT>, FlatListProps<ItemT>,
| 'onScroll' // Use ScrollContext instead. | 'onScroll' // Use ScrollContext instead.
@@ -147,10 +152,16 @@ function ListImpl<ItemT>(
scrollBy(options: ScrollToOptions) { scrollBy(options: ScrollToOptions) {
element.scrollBy(options) element.scrollBy(options)
}, },
addEventListener(event: string, handler: any) { addEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
element.addEventListener(event, handler) element.addEventListener(event, handler)
}, },
removeEventListener(event: string, handler: any) { removeEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
element.removeEventListener(event, handler) element.removeEventListener(event, handler)
}, },
} }
@@ -180,10 +191,16 @@ function ListImpl<ItemT>(
scrollBy(options: ScrollToOptions) { scrollBy(options: ScrollToOptions) {
window.scrollBy(options) window.scrollBy(options)
}, },
addEventListener(event: string, handler: any) { addEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
window.addEventListener(event, handler) window.addEventListener(event, handler)
}, },
removeEventListener(event: string, handler: any) { removeEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
window.removeEventListener(event, handler) window.removeEventListener(event, handler)
}, },
} }
@@ -193,35 +210,28 @@ function ListImpl<ItemT>(
const nativeRef = useRef<HTMLDivElement>(null) const nativeRef = useRef<HTMLDivElement>(null)
useImperativeHandle( useImperativeHandle(
ref, ref,
() => () => ({
({ scrollToTop() {
scrollToTop() { getScrollableNode()?.scrollTo({top: 0})
getScrollableNode()?.scrollTo({top: 0}) },
},
scrollToOffset({ scrollToOffset({animated, offset}: {animated: boolean; offset: number}) {
animated, getScrollableNode()?.scrollTo({
offset, left: 0,
}: { top: offset,
animated: boolean behavior: animated ? 'smooth' : 'instant',
offset: number })
}) { },
getScrollableNode()?.scrollTo({
left: 0,
top: offset,
behavior: animated ? 'smooth' : 'instant',
})
},
scrollToEnd({animated = true}: {animated?: boolean}) { scrollToEnd({animated = true} = {}) {
const element = getScrollableNode() const element = getScrollableNode()
element?.scrollTo({ element?.scrollTo({
left: 0, left: 0,
top: element.scrollHeight, top: element.scrollHeight,
behavior: animated ? 'smooth' : 'instant', behavior: animated ? 'smooth' : 'instant',
}) })
}, },
}) as any, // TODO: Better types. }),
[getScrollableNode], [getScrollableNode],
) )
@@ -257,7 +267,7 @@ function ListImpl<ItemT>(
| 'targetContentOffset' | 'targetContentOffset'
| 'contentInset' | 'contentInset'
>, >,
null as any, {},
) )
}) })
@@ -326,7 +336,7 @@ function ListImpl<ItemT>(
'overflow-y': 'scroll', 'overflow-y': 'scroll',
}, },
]} ]}
ref={nativeRef as any}> ref={nativeRef as unknown as React.RefObject<View>}>
<Visibility <Visibility
onVisibleChange={setIsInsideVisibleTree} onVisibleChange={setIsInsideVisibleTree}
style={ style={
@@ -454,9 +464,9 @@ let Row = function RowImpl<ItemT>({
renderItem: renderItem:
| null | null
| undefined | undefined
| ((data: {index: number; item: any; separators: any}) => React.ReactNode) | ((info: ListRenderItemInfo<ItemT>) => React.ReactNode)
extraData: any extraData: unknown
onItemSeen: ((item: any) => void) | undefined onItemSeen: ((item: ItemT) => void) | undefined
}): React.ReactNode { }): React.ReactNode {
const rowRef = useRef(null) const rowRef = useRef(null)
const intersectionTimeout = useRef<ReturnType<typeof setTimeout> | undefined>( const intersectionTimeout = useRef<ReturnType<typeof setTimeout> | undefined>(
@@ -513,11 +523,24 @@ let Row = function RowImpl<ItemT>({
return ( return (
<View ref={rowRef}> <View ref={rowRef}>
{renderItem({item, index, separators: null as any})} {renderItem({
item,
index,
separators: null as unknown as ListRenderItemInfo<ItemT>['separators'],
})}
</View> </View>
) )
} }
Row = memo(Row) Row = memo(Row) as <ItemT>(props: {
item: ItemT
index: number
renderItem:
| null
| undefined
| ((info: ListRenderItemInfo<ItemT>) => React.ReactNode)
extraData: unknown
onItemSeen: ((item: ItemT) => void) | undefined
}) => React.ReactNode
let Visibility = ({ let Visibility = ({
root, root,
@@ -572,7 +595,7 @@ Visibility = memo(Visibility)
export const List = memo(forwardRef(ListImpl)) as <ItemT>( export const List = memo(forwardRef(ListImpl)) as <ItemT>(
props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>}, props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>},
) => React.ReactElement<any> ) => React.ReactElement
// https://stackoverflow.com/questions/7944460/detect-safari-browser // https://stackoverflow.com/questions/7944460/detect-safari-browser