Skip to content

fix: six real bugs the old TypeScript config was hiding - #1

Merged
ludejun merged 1 commit into
masterfrom
chore/maintenance-2026
Sep 23, 2026
Merged

ludejun merged 1 commit into
masterfrom
chore/maintenance-2026

Conversation

@ludejun

@ludejun ludejun commented Sep 23, 2026

Copy link
Copy Markdown
Owner

Note

React Native stays on 0.68. Moving to 0.87 crosses the New Architecture (Fabric / TurboModules) and means regenerating ios/ and android/ — work that needs Xcode and the Android SDK to verify, not something the JavaScript side can settle. This PR covers everything that can be done without them.

TypeScript 4.5 could not even parse the installed @types/node, and suppressImplicitAnyIndexErrors (removed in TS 5.5) was suppressing the rest. Upgrading to 5.9 and dropping that flag surfaced six genuine bugs — five of them runtime, not type-only.

The bugs

Per-device font sizing never ran TextInput imported deviceType from the utils barrel, which only re-exports it under its alias isIOS. The import was undefined, so if (!deviceType) return 14 always took the first branch.
Two environments had no API domain Env has eight members; apiServer defined six. local and bcp resolved to undefined, making the request base URL the literal string "undefined". Now typed Record<Env, string>, so a missing environment is a compile error.
The anti-double-submit Button never guarded anything It declared a loading prop, tracked iLoading, and called setLoading(true) on press — but neither value was read anywhere in the component. Repeat presses went straight through. Presses during an in-flight onPress are now ignored.
Webview was not a valid navigation screen It declared its own route shape, not assignable to React Navigation's ScreenComponentType. Now uses RouteProp with typed params. The || restProps fallback beside it was dead code — restProps only carries the connected props, never url / header / disableBottom.
The tab badge always read 0 TabScreen required homeTodoCount, but its connect() is commented out, so nothing supplied it.
The only test could never pass __tests__/App-test.tsx imported '../App', while App.tsx lives in src/. On a case-insensitive filesystem that resolved to app.json, so React was handed an object.

Toolchain

  • TypeScript 4.5 → 5.9, suppressImplicitAnyIndexErrors removed. 0 type errors.
  • The test stack was internally inconsistent: jest 25 with babel-jest 28, @types/jest 27, and react-test-renderer 16 against React 18. Now jest 29 throughout.
  • transformIgnorePatterns matches the React Native packages anywhere in the path — pnpm nests them under node_modules/.pnpm/… and the preset's own pattern assumes a flat node_modules.
  • The whole-<App /> render test is replaced by 17 unit tests over the validation helpers (phone, bank card, ID card, URL, and the password rules). Rendering the full app needs every native module mocked and does not finish in CI.
  • ESLint accepts _-prefixed unused bindings. 0 errors.
  • Migrated to pnpm.

Docs

  • English README_EN.md alongside the Chinese readme.md, both with badges and a plain statement of where React Native stands.
  • New CHANGELOG.md and bilingual CONTRIBUTING.md.
  • New ci.yml running lint, type-check and tests on Node 20 and 22 — deliberately not the app builds.

Verified

pnpm lint (0 errors), pnpm tslint (0 errors) and pnpm test (17 passing) all pass. The native builds were not run.

🤖 Generated with Claude Code

React Native stays on 0.68 — moving to 0.87 crosses the New Architecture and
means regenerating the native projects, which needs Xcode and the Android SDK
to verify. This covers the JavaScript side, where TypeScript 4.5 plus
`suppressImplicitAnyIndexErrors` was hiding real problems.

- TextInput imported `deviceType` from the utils barrel, which only re-exports
  it as `isIOS`. The import was undefined at runtime, so
  `if (!deviceType) return 14` always took the first branch and the per-device
  font sizing never ran.
- `Env` has eight members but `apiServer` defined six: `local` and `bcp`
  resolved to undefined, making the request base URL the string "undefined".
  The map is now Record<Env, string>, so a missing environment is a type error.
- The anti-double-submit Button never guarded anything. It declared a `loading`
  prop and tracked `iLoading`, and setLoading(true) ran on press, but neither
  value was read anywhere. Presses during an in-flight onPress are now ignored.
- Webview was not assignable to React Navigation's ScreenComponentType: it
  declared its own `route` shape. It now uses RouteProp with typed params. The
  `|| restProps` fallback beside it was dead — restProps only carries the
  connected props.
- TabScreen required `homeTodoCount`, but its connect() is commented out, so it
  was always undefined and the badge always read 0.
- __tests__/App-test.tsx imported '../App', while App.tsx lives in src/. On a
  case-insensitive filesystem that resolved to app.json, so React was handed an
  object.

Toolchain
- TypeScript 4.5 -> 5.9; 4.5 could not parse the installed @types/node.
  Dropped `suppressImplicitAnyIndexErrors`, removed in TS 5.5. 0 type errors.
- Test stack realigned: it was jest 25 with babel-jest 28, @types/jest 27 and
  react-test-renderer 16 against React 18. Now jest 29 throughout.
- transformIgnorePatterns matches the React Native packages anywhere in the
  path: pnpm nests them under node_modules/.pnpm/, and the preset's own pattern
  assumes a flat node_modules.
- The whole-<App /> render test is replaced by 17 unit tests over the
  validation helpers. Rendering the full app needs every native module mocked
  and does not finish in CI.
- ESLint accepts _-prefixed unused bindings. 0 errors.
- Migrate to pnpm.

Docs
- English README_EN.md alongside the Chinese readme.md, both stating plainly
  where React Native stands.
- New CHANGELOG.md, bilingual CONTRIBUTING.md, and a CI workflow that runs
  lint, type-check and tests (not the app builds).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ludejun
ludejun merged commit 71a0f2b into master Sep 23, 2026
2 checks passed
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.

2 participants