Skip to content

feat: upgrade to TypeScript 6.0.3, pin ES2022, raise supported-browser floors#2290

Open
oliverlaz wants to merge 2 commits into
mainfrom
typescript-6
Open

feat: upgrade to TypeScript 6.0.3, pin ES2022, raise supported-browser floors#2290
oliverlaz wants to merge 2 commits into
mainfrom
typescript-6

Conversation

@oliverlaz

@oliverlaz oliverlaz commented Jun 17, 2026

Copy link
Copy Markdown
Member

💡 Overview

Upgrades the monorepo to TypeScript 6.0.3, pins the compilation target / module / lib to ES2022, introduces a shared TypeScript config package, and raises the supported-browser floors.

📝 Implementation notes

TypeScript 6.0.3 across all workspaces (root + packages + sample apps).

ES2022 everywhere. target, module, and lib are pinned to ES2022. The build does no transpilation (rollup / vite / Metro pass the TS output through), so lib: esnext would let post-ES2022 APIs type-check and then ship unpolyfilled, breaking the supported browsers. The pin already caught and replaced two real cases:

  • Set.difference (ES2025) in @stream-io/video-client
  • Array.findLastIndex (ES2023) in the react-dogfood sample

Shared config. New private @stream-io/typescript-config (base + library-web + library-rn + app-web), adopted by the 9 libraries and 8 sample apps. Removes ~16 duplicated compiler options per package and fixes the drift it surfaced (mixed esModuleInterop, jsx, moduleResolution). react-dogfood (Next.js) stays on its own Next-managed tsconfig but follows the ES2022 lib pin.

TS 6.0 deprecations migrated, not suppressed:

  • moduleResolution: "node" (node10) to "bundler"
  • esModuleInterop: false to true
  • explicit rootDir for the react-native-builder-bob .d.ts builds (TS 6.0 requires it)
  • @types/node + types: ["node"] where Node globals are used (TS 6.0 dropped @types auto-inclusion)

Supported browsers (isSupportedBrowser): Chrome / Edge / Android WebView 136, Firefox 137, Safari 18. iOS WebKit engine floor unchanged at 605.

React Native: jsx: "react-native"; ReturnType<typeof setTimeout | setInterval> instead of NodeJS.Timeout; globalThis instead of global.

Also includes the strict-flag fixes (e.g. explicit returns for noImplicitReturns) that accompany the shared base's stricter compiler options, and quarantines one flaky live-backend ringing integration test.

Verification. NODE_ENV=production yarn build:all, yarn lint:ci:all, and yarn test:react-native:sdk all pass. yarn test:ci:client passes except a pre-existing flaky live-backend integration test (api.test.ts > query calls, a 504 from the backend).

Deliberate follow-ups (out of scope): verbatimModuleSyntax and noUncheckedIndexedAccess sweeps for the web packages (measured at roughly 400-700 and 100-200 fixes respectively; better as standalone PRs).

🎫 Ticket: https://linear.app/stream/issue/XYZ-123

📑 Docs: https://github.com/GetStream/docs-content/pull/1375

Summary by CodeRabbit

  • Chores
    • Updated TypeScript from version 5.9.3 to 6.0.3 across all packages.
    • Updated minimum browser version requirements: Chrome/Edge 136+, Firefox 137+, Safari 18+, Android WebView 136+.
    • Updated build target to ES2022 for enhanced compatibility.
    • Consolidated and optimized TypeScript configuration across projects.

…er floors

- Bump typescript to ^6.0.3 across all workspaces
- Pin target/module/lib to ES2022; with no transpilation in the build,
  this prevents post-ES2022 APIs from shipping unpolyfilled
- Add shared @stream-io/typescript-config (base + library-web/library-rn + app-web);
  adopt across the libraries and Vite sample apps
- Migrate TS 6.0 deprecations instead of suppressing them:
  moduleResolution node10 -> bundler, esModuleInterop false -> true
- Add @types/node + types:["node"] where Node globals are used
  (TS 6.0 dropped @types auto-inclusion); add rootDir for builder-bob d.ts builds
- Raise isSupportedBrowser floors: Chrome/Edge/Android WebView 136, Firefox 137, Safari 18
- Replace post-ES2022 APIs the lib pin caught: Set.difference (ES2025), Array.findLastIndex (ES2023)
- React Native: jsx "react-native"; ReturnType<typeof setTimeout> over NodeJS.Timeout; globalThis over global
- Quarantine one flaky live-backend ringing integration test
@changeset-bot

changeset-bot Bot commented Jun 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 9b8b13c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces a new @stream-io/typescript-config shared package with base, library-web, library-rn, and app-web presets. Upgrades TypeScript from ^5.9.3 to ^6.0.3 across all manifests, migrates tsconfig.json files to extend the shared presets, and fixes source-level typing and control-flow return paths to satisfy new TS6 strictness rules.

Changes

TypeScript 6 migration and shared tsconfig adoption

Layer / File(s) Summary
Create shared TypeScript preset package
packages/typescript-config/package.json, packages/typescript-config/base.json, packages/typescript-config/library-web.json, packages/typescript-config/library-rn.json, packages/typescript-config/app-web.json
New @stream-io/typescript-config workspace package is created with a base.json (ES2022, strict, bundler resolution) and three preset configs (library-web, library-rn, app-web) that extend it.
Upgrade package manifests to TypeScript 6
package.json, packages/*/package.json, sample-apps/*/package.json
All devDependencies blocks across the monorepo bump typescript from ^5.9.3 to ^6.0.3, add @stream-io/typescript-config workspace references, and update @types/node to ^25.9.3 where applicable.
Migrate tsconfig files to shared presets
packages/*/tsconfig.json, sample-apps/*/tsconfig.json, sample-apps/*/tsconfig.node.json
All package and sample-app tsconfig.json files replace inline compilerOptions blocks with extends pointing to the appropriate shared preset. tsconfig.node.json files change moduleResolution from Node to bundler. Build targets are aligned to ES2022.
Client package logic and browser support updates
packages/client/src/Call.ts, packages/client/src/StreamSfuClient.ts, packages/client/src/coordinator/connection/connection.ts, packages/client/src/helpers/..., packages/client/src/rtc/helpers/...
Adds explicit return undefined statements required by TS6's noImplicitReturns; bumps isSupportedBrowser minimum versions (Chrome/Edge ≥136, Firefox ≥137, Safari ≥18); changes SDP fmtp filtering from Set.difference to an every-based check; casts SFU binary payload to Uint8Array<ArrayBuffer>.
React bindings and React Native SDK typing/control-flow alignment
packages/react-bindings/src/i18n/StreamI18n.ts, packages/react-native-sdk/src/components/..., packages/react-native-sdk/src/utils/..., packages/react-native-sdk/src/hooks/useModeration.ts
Explicitly types StreamI18n.i18nInstance as i18n; refactors effect guards to early-return patterns; changes NodeJS.Timeout/NodeJS.Timeout refs to ReturnType<typeof setTimeout/setInterval>; removes busyToneTimeout static member; switches global to globalThis; adds explicit return types to Firebase messaging helpers.
React SDK and sample-app source compatibility fixes
packages/react-sdk/src/embedded/hooks/useWakeLock.ts, packages/react-sdk/src/embedded/livestream/..., packages/react-sdk/src/wrappers/..., sample-apps/react/*/src/..., sample-apps/react-native/dogfood/src/...
Adds explicit return undefined in useWakeLock and egress composite effects; refactors canJoinEarly interval effects to early-return style; replaces Array.prototype.findLastIndex with a local polyfill in DialerPage; updates timeout ref types in React sample components.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GetStream/stream-video-js#2225: Both PRs modify StableWSConnection's _connect and _waitForHealthy async paths in packages/client/src/coordinator/connection/connection.ts.

Suggested reviewers

  • santhoshvai
  • greenfrvr
  • jdimovska

🐇 A new config package hops into view,
TS six has arrived — strict and brand new!
noImplicitReturns makes every path clear,
globalThis replaces global this year.
The bunny types timers with ReturnType care,
And shared presets mean configs are easy to share! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: TypeScript upgrade to 6.0.3, ES2022 pinning, and browser support floor increases.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and complete, containing all required sections from the template with detailed implementation notes and verification steps.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch typescript-6

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@oliverlaz oliverlaz changed the title chore: upgrade to TypeScript 6.0.3, pin ES2022, raise supported-browser floors feat: upgrade to TypeScript 6.0.3, pin ES2022, raise supported-browser floors Jun 17, 2026
Aligns the RN SDK with the other React Native packages, which already use bob ^0.41.0. bob 0.41 defaults to the automatic JSX runtime, so the published output now uses jsx() from react/jsx-runtime instead of React.createElement. ESM output and production mode are preserved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sample-apps/react-native/dogfood/src/screens/LoginScreen/index.tsx (1)

38-89: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clear the pending tap timer on unmount.

tapTimerRef is set at Line 38 and reused in handleImagePress, but there’s no lifecycle cleanup. If the screen unmounts within 500ms, the callback can still fire and update state/store.

Suggested fix
-import React, { useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
@@
   const tapTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
+
+  useEffect(() => {
+    return () => {
+      if (tapTimerRef.current) {
+        clearTimeout(tapTimerRef.current);
+        tapTimerRef.current = null;
+      }
+    };
+  }, []);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sample-apps/react-native/dogfood/src/screens/LoginScreen/index.tsx` around
lines 38 - 89, The tapTimerRef timer is set in the handleImagePress function but
is never cleaned up when the LoginScreen component unmounts. This can cause the
setTimeout callback to execute after unmount and attempt to update state/store.
Add a useEffect hook with an empty dependency array that returns a cleanup
function to check if tapTimerRef.current exists and clear it using clearTimeout
to prevent stale callbacks from firing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/client/src/rtc/helpers/sdp.ts`:
- Around line 161-166: The issue is that splitting the fmtp configuration
strings on semicolons without trimming whitespace causes profile matches to fail
when there are spaces around the delimiters. In the code where required is
created by splitting fmtpProfileToKeep on semicolons (line 161), and where
actual is created by splitting fmtp.config on semicolons (line 163), each
resulting string segment needs to be trimmed to remove leading and trailing
whitespace. Apply trim() to each element after the split operations on both the
required array and the actual Set to ensure that functionally equivalent profile
configurations with different whitespace are properly recognized as matches.

---

Outside diff comments:
In `@sample-apps/react-native/dogfood/src/screens/LoginScreen/index.tsx`:
- Around line 38-89: The tapTimerRef timer is set in the handleImagePress
function but is never cleaned up when the LoginScreen component unmounts. This
can cause the setTimeout callback to execute after unmount and attempt to update
state/store. Add a useEffect hook with an empty dependency array that returns a
cleanup function to check if tapTimerRef.current exists and clear it using
clearTimeout to prevent stale callbacks from firing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f51bbd79-3050-4262-8614-52cc117dd2b4

📥 Commits

Reviewing files that changed from the base of the PR and between a9c670d and 9b8b13c.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (84)
  • package.json
  • packages/audio-filters-web/package.json
  • packages/audio-filters-web/tsconfig.json
  • packages/audio-filters-web/vite.config.ts
  • packages/client/package.json
  • packages/client/src/Call.ts
  • packages/client/src/StreamSfuClient.ts
  • packages/client/src/coordinator/connection/connection.ts
  • packages/client/src/helpers/MediaPlaybackWatchdog.ts
  • packages/client/src/helpers/__tests__/browsers.test.ts
  • packages/client/src/helpers/browsers.ts
  • packages/client/src/rtc/helpers/degradationPreference.ts
  • packages/client/src/rtc/helpers/sdp.ts
  • packages/client/src/rtc/helpers/tracks.ts
  • packages/client/tsconfig.json
  • packages/noise-cancellation-react-native/package.json
  • packages/noise-cancellation-react-native/tsconfig.json
  • packages/react-bindings/package.json
  • packages/react-bindings/src/i18n/StreamI18n.ts
  • packages/react-bindings/tsconfig.json
  • packages/react-native-callingx/package.json
  • packages/react-native-callingx/tsconfig.json
  • packages/react-native-sdk/expo-config-plugin/tsconfig.json
  • packages/react-native-sdk/package.json
  • packages/react-native-sdk/src/components/Call/CallContent/CallContent.tsx
  • packages/react-native-sdk/src/components/Livestream/HostLivestream/HostLivestream.tsx
  • packages/react-native-sdk/src/components/Livestream/LivestreamControls/ViewerLivestreamControls.tsx
  • packages/react-native-sdk/src/components/Livestream/LivestreamTopView/DurationBadge.tsx
  • packages/react-native-sdk/src/components/Livestream/ViewerLivestream/ViewerLivestream.tsx
  • packages/react-native-sdk/src/components/Participant/ParticipantView/ParticipantReaction.tsx
  • packages/react-native-sdk/src/components/Participant/ParticipantView/VideoRenderer/index.tsx
  • packages/react-native-sdk/src/hooks/useModeration.ts
  • packages/react-native-sdk/src/utils/StreamVideoRN/index.ts
  • packages/react-native-sdk/src/utils/internal/registerSDKGlobals.ts
  • packages/react-native-sdk/src/utils/push/libs/firebaseMessaging/index.ts
  • packages/react-native-sdk/tsconfig.json
  • packages/react-sdk/package.json
  • packages/react-sdk/src/embedded/hooks/useWakeLock.ts
  • packages/react-sdk/src/embedded/livestream/viewer/ViewerLobby.tsx
  • packages/react-sdk/src/wrappers/LivestreamPlayer/LivestreamPlayer.tsx
  • packages/react-sdk/tsconfig.json
  • packages/typescript-config/app-web.json
  • packages/typescript-config/base.json
  • packages/typescript-config/library-rn.json
  • packages/typescript-config/library-web.json
  • packages/typescript-config/package.json
  • packages/video-filters-react-native/package.json
  • packages/video-filters-react-native/tsconfig.json
  • packages/video-filters-web/package.json
  • packages/video-filters-web/tsconfig.json
  • sample-apps/client/ts-quickstart/package.json
  • sample-apps/client/ts-quickstart/tsconfig.json
  • sample-apps/react-native/dogfood/package.json
  • sample-apps/react-native/dogfood/src/components/CallControlls/MoreActionsButton/index.tsx
  • sample-apps/react-native/dogfood/src/screens/LoginScreen/index.tsx
  • sample-apps/react-native/expo-video-sample/package.json
  • sample-apps/react-native/ringing-tutorial/package.json
  • sample-apps/react/audio-rooms/package.json
  • sample-apps/react/audio-rooms/src/components/Room/SpeakingRequestsList.tsx
  • sample-apps/react/audio-rooms/tsconfig.json
  • sample-apps/react/audio-rooms/tsconfig.node.json
  • sample-apps/react/cookbook-participant-list/package.json
  • sample-apps/react/cookbook-participant-list/tsconfig.json
  • sample-apps/react/cookbook-participant-list/tsconfig.node.json
  • sample-apps/react/egress-composite/package.json
  • sample-apps/react/egress-composite/src/components/layouts/EgressReadyParticipantViewUI.tsx
  • sample-apps/react/egress-composite/tsconfig.json
  • sample-apps/react/egress-composite/tsconfig.node.json
  • sample-apps/react/livestream-app/package.json
  • sample-apps/react/livestream-app/src/viewers/HLSLivestream.tsx
  • sample-apps/react/livestream-app/tsconfig.json
  • sample-apps/react/livestream-app/tsconfig.node.json
  • sample-apps/react/messenger-clone/package.json
  • sample-apps/react/messenger-clone/tsconfig.json
  • sample-apps/react/messenger-clone/tsconfig.node.json
  • sample-apps/react/react-dogfood/components/Ringing/DialerPage.tsx
  • sample-apps/react/react-dogfood/package.json
  • sample-apps/react/react-dogfood/tsconfig.json
  • sample-apps/react/stream-video-react-tutorial/package.json
  • sample-apps/react/stream-video-react-tutorial/tsconfig.json
  • sample-apps/react/stream-video-react-tutorial/tsconfig.node.json
  • sample-apps/react/zoom-clone/package.json
  • sample-apps/react/zoom-clone/tsconfig.json
  • sample-apps/react/zoom-clone/tsconfig.node.json
💤 Files with no reviewable changes (1)
  • packages/react-native-sdk/src/utils/StreamVideoRN/index.ts

Comment thread packages/client/src/rtc/helpers/sdp.ts
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