Skip to content

[No QA] Split app TypeScript into web and native programs - #99495

Draft
roryabraham wants to merge 23 commits into
mainfrom
rory/tsconfig-cleanup-phase-2
Draft

[No QA] Split app TypeScript into web and native programs#99495
roryabraham wants to merge 23 commits into
mainfrom
rory/tsconfig-cleanup-phase-2

Conversation

@roryabraham

@roryabraham roryabraham commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Phase 2 of the tsconfig cleanup: typecheck the app as separate web and native programs instead of one mega-program.

  • Add tsconfig.app.web.json (moduleSuffixes: [".web", ""], DOM, RN-web) and tsconfig.app.native.json (moduleSuffixes: [".ios", ".android", ".native", ""], no DOM).
  • Point npm run typecheck at web + native + Jest + Bun + Node + VCR.
  • Move Window / Document / Navigator / env ambients off the native graph (src/types/web, src/types/app, types/env.d.ts).
  • Keep Metro NodeRequire on both app programs.
  • Extend the merged Jest project with web suffix resolution and exclude native-only roots.

The dedicated Jest project from #100124 makes the previous Jest-global restrictions and separate Jest/mocks ESLint mappings unnecessary, so those have been removed. ESLint retains only the web/native project mappings required for correct typed linting.

Fixed Issues

$ #99287

Tests

  1. Run npm run typecheck and verify it checks tsconfig.app.web.json, tsconfig.app.native.json, tsconfig.jest.json, tsconfig.bun.json, tsconfig.node.json, and VCR.
  2. Confirm a document / window use in a .native.ts file is a type error under tsconfig.app.native.json.
  3. Run npm run lint-changed and verify it passes.
  • Verify that no errors appear in the JS console

Offline tests

n/a

QA Steps

Same as tests.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (not applicable: tooling-only change)
    • I turned off my network connection and tested it while offline (not applicable: tooling-only change)
    • I tested this PR with a High Traffic account (not applicable: tooling-only change)
  • I included screenshots or videos for tests on all platforms (not applicable: tooling-only change)
  • I ran the tests on all platforms & verified they passed on (not applicable: tooling-only change):
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (not applicable: tooling-only change)
  • I followed proper code patterns
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained why
    • I verified any copy/text added to the app is grammatically correct (not applicable)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the Review Guidelines
  • I tested other components that can be impacted by my changes (not applicable)
  • If a new CSS style is added I verified it (not applicable)
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function
  • If new assets were added or existing ones were modified (not applicable)
    • The assets are optimized and compressed
    • The assets load correctly across all supported platforms
  • If the PR modifies code that runs when editing or sending messages, I tested markdown behavior (not applicable)
  • If the PR modifies a generic component, I tested impacted usages (not applicable)
  • If the PR modifies a component related to Storybook stories, I verified stories (not applicable)
  • If the PR modifies a page accessible by deeplink, I verified deeplinks (not applicable)
  • If the PR modifies UI or form input styles, I verified alignment and design review (not applicable)
  • I added unit tests for any new feature or bug fix (not applicable: configuration-only change)
  • If main was merged after review, I tested again

Screenshots/Videos

Not applicable: tooling-only change.

Phase 2 of the tsconfig cleanup: typecheck src as separate web (DOM +
.web suffixes) and native (no DOM + ios/android/native suffixes)
projects instead of one mega-program. Move Window/Document/env ambients
off the native graph, point ESLint src/** at the web project, and
restrict Jest globals in app code.
@melvin-bot

melvin-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers!

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/CONFIG.ts 84.84% <100.00%> (ø)
src/components/AttachmentPicker/index.native.tsx 19.58% <ø> (ø)
...uggestions/AutoCompleteSuggestionsPortal/index.tsx 0.00% <ø> (ø)
...c/components/DragAndDrop/Consumer/index.native.tsx 100.00% <ø> (ø)
...onents/FeatureTraining/primitives/Illustration.tsx 88.37% <100.00%> (ø)
src/components/FormElement/index.native.tsx 100.00% <ø> (ø)
src/components/FormElement/index.tsx 0.00% <ø> (ø)
src/components/Lottie/index.tsx 81.35% <100.00%> (ø)
src/components/MenuItemGroup.tsx 100.00% <ø> (ø)
...ents/Modal/useSyncModalWithHistory/index.native.ts 100.00% <100.00%> (ø)
... and 86 more
... and 16 files with indirect coverage changes

Drop unused type re-exports from platform index files, restore the
native PopoverProvider no-arg stubs the compiler already accepted,
and rephrase the evals README so cspell does not flag typechecks.
Native typecheck still includes unsuffixed Popover callers that pass
an argument to close/onOpen. Optional params on the type keep those
calls valid; implementations stay no-arg so the React Compiler and
eslint unused-vars stay clean.
…-phase-2

# Conflicts:
#	src/components/FeatureTraining/primitives/Illustration.tsx
#	src/hooks/useSingleExecution/index.native.ts
#	src/libs/Pusher/index.native.ts
…-phase-2

# Conflicts:
#	tests/ui/WorkspaceCompanyCardPageEmptyStateTest.tsx
@roryabraham

Copy link
Copy Markdown
Contributor Author

Replaced the native-only no-unused-vars relaxation with explicit shared contracts for cross-platform APIs. No-op implementations now export the same consumer signatures while omitting unused implementation parameters; the normal lint rule remains enabled.

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.

1 participant