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
}
},
"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": {
"@typescript-eslint/no-explicit-any": {
"count": 2
+3 -1
View File
@@ -18,6 +18,8 @@ import {IS_IOS} from '#/env'
import {FlatList_INTERNAL} from './Views'
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<
FlatListPropsWithLayout<ItemT>,
| 'onMomentumScrollBegin' // Use ScrollContext instead.
@@ -58,7 +60,7 @@ let List = forwardRef<ListMethods, ListProps>(
...props
},
ref,
): React.ReactElement<any> => {
): React.ReactElement => {
const isScrolledDown = useSharedValue(false)
const t = useTheme()
const dedupe = useDedupe(400)
+63 -40
View File
@@ -11,6 +11,7 @@ import {
} from 'react'
import {
type FlatListProps,
type ListRenderItemInfo,
StyleSheet,
View,
type ViewProps,
@@ -23,7 +24,11 @@ import {useScrollHandlers} from '#/lib/ScrollContext'
import {addStyle} from '#/lib/styles'
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<
FlatListProps<ItemT>,
| 'onScroll' // Use ScrollContext instead.
@@ -147,10 +152,16 @@ function ListImpl<ItemT>(
scrollBy(options: ScrollToOptions) {
element.scrollBy(options)
},
addEventListener(event: string, handler: any) {
addEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
element.addEventListener(event, handler)
},
removeEventListener(event: string, handler: any) {
removeEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
element.removeEventListener(event, handler)
},
}
@@ -180,10 +191,16 @@ function ListImpl<ItemT>(
scrollBy(options: ScrollToOptions) {
window.scrollBy(options)
},
addEventListener(event: string, handler: any) {
addEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
window.addEventListener(event, handler)
},
removeEventListener(event: string, handler: any) {
removeEventListener(
event: string,
handler: EventListenerOrEventListenerObject,
) {
window.removeEventListener(event, handler)
},
}
@@ -193,35 +210,28 @@ function ListImpl<ItemT>(
const nativeRef = useRef<HTMLDivElement>(null)
useImperativeHandle(
ref,
() =>
({
scrollToTop() {
getScrollableNode()?.scrollTo({top: 0})
},
() => ({
scrollToTop() {
getScrollableNode()?.scrollTo({top: 0})
},
scrollToOffset({
animated,
offset,
}: {
animated: boolean
offset: number
}) {
getScrollableNode()?.scrollTo({
left: 0,
top: offset,
behavior: animated ? 'smooth' : 'instant',
})
},
scrollToOffset({animated, offset}: {animated: boolean; offset: number}) {
getScrollableNode()?.scrollTo({
left: 0,
top: offset,
behavior: animated ? 'smooth' : 'instant',
})
},
scrollToEnd({animated = true}: {animated?: boolean}) {
const element = getScrollableNode()
element?.scrollTo({
left: 0,
top: element.scrollHeight,
behavior: animated ? 'smooth' : 'instant',
})
},
}) as any, // TODO: Better types.
scrollToEnd({animated = true} = {}) {
const element = getScrollableNode()
element?.scrollTo({
left: 0,
top: element.scrollHeight,
behavior: animated ? 'smooth' : 'instant',
})
},
}),
[getScrollableNode],
)
@@ -257,7 +267,7 @@ function ListImpl<ItemT>(
| 'targetContentOffset'
| 'contentInset'
>,
null as any,
{},
)
})
@@ -326,7 +336,7 @@ function ListImpl<ItemT>(
'overflow-y': 'scroll',
},
]}
ref={nativeRef as any}>
ref={nativeRef as unknown as React.RefObject<View>}>
<Visibility
onVisibleChange={setIsInsideVisibleTree}
style={
@@ -454,9 +464,9 @@ let Row = function RowImpl<ItemT>({
renderItem:
| null
| undefined
| ((data: {index: number; item: any; separators: any}) => React.ReactNode)
extraData: any
onItemSeen: ((item: any) => void) | undefined
| ((info: ListRenderItemInfo<ItemT>) => React.ReactNode)
extraData: unknown
onItemSeen: ((item: ItemT) => void) | undefined
}): React.ReactNode {
const rowRef = useRef(null)
const intersectionTimeout = useRef<ReturnType<typeof setTimeout> | undefined>(
@@ -513,11 +523,24 @@ let Row = function RowImpl<ItemT>({
return (
<View ref={rowRef}>
{renderItem({item, index, separators: null as any})}
{renderItem({
item,
index,
separators: null as unknown as ListRenderItemInfo<ItemT>['separators'],
})}
</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 = ({
root,
@@ -572,7 +595,7 @@ Visibility = memo(Visibility)
export const List = memo(forwardRef(ListImpl)) as <ItemT>(
props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>},
) => React.ReactElement<any>
) => React.ReactElement
// https://stackoverflow.com/questions/7944460/detect-safari-browser