The main typecheck models native resolution (.ios/.android/.native), so
.web variants were never checked in their real resolution context. Add a
second pass that roots the program at the web entry point and resolves
with moduleSuffixes [".web", ""], wire it up as pnpm typecheck:web, and
add it to the lint workflow matrix.
Ambient shims (src/platform/*.web-check.d.ts, web pass only) pin
react-native-svg, expo-file-system, and expo-image-manipulator to their
native declarations, since their .web.d.ts files expose a different API
surface than the one the app is written against (and, for
expo-file-system/legacy, raw package sources that break under suffix
remapping).
The rest fixes the drift the new pass surfaced, notably:
- List.web: ListRef now carries ListMethods (was RefObject<View>),
scrollToOffset accepts optional animated, ListProps defaults ItemT
- Dialog.web: ScrollableInner accepts a (never-attached) ScrollView ref,
InnerFlatList label optional + ListMethods ref, Handle accepts props
- Menu.web exports MenuControlProps; ContextMenu.web gets a properly
typed Trigger wrapper and accepts align
- Pager/TabBar/PagerWithHeader web variants align with the shared
contract (testID, onTabPressed, drag shared values, setMinimumHeight)
- useNavigationTabState.web now reports isAtFeeds/isAtBookmarks, fixing
drawer highlighting for those routes on web
- Web-only throw-stubs get real signatures; duplicated prop types move
into .shared.ts files (CaptchaWebView, EditImageDialog, OpenCameraBtn,
GestureActionView, ValuePropositionPager)
- findListNativeTag helper replaces findNodeHandle casts on List refs
- Assorted call-site type fixes (keyExtractor params, PostQuotes record
narrowing, saveBytesToDisk bytes param, openCamera web signature)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCuMKXWHuyGoNhTVAHBMyk