Skip to content

chore(other): upgrade TypeScript from 5.8 to 6.0.3 - #3159

Open
bc-0dp wants to merge 1 commit into
bigcommerce:masterfrom
bc-0dp:upgrade/typescript-6
Open

chore(other): upgrade TypeScript from 5.8 to 6.0.3#3159
bc-0dp wants to merge 1 commit into
bigcommerce:masterfrom
bc-0dp:upgrade/typescript-6

Conversation

@bc-0dp

@bc-0dp bc-0dp commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

What/Why?

Requires that checkout-sdk-js PR for TypeScript 6.0.3 is is also merged and version bumped here and there.

Upgrades the workspace from TypeScript 5.8 to 6.0.3. TypeScript 6.0 is the final "Strada" (JS-based) release and a deliberate bridge to TypeScript 7.0 (the native "Corsa" port), landing the deprecations and default changes needed to prepare for it. This bump gets us onto a supported line and de-risks the eventual TS7 migration.

Toolchain

  • typescript 5.8.36.0.3 (pinned exact)
  • ts-jest 29.1.529.4.11 (peer range widened to allow TS6)
  • ts-loader ^9.3.0^9.6.2 (TS6 program support)
  • Added scoped npm overrides so the internal @bigcommerce/eslint-plugin / @bigcommerce/eslint-config accept the TS6 peer range (their metadata still pins ^4 || ^5; they delegate to @typescript-eslint v8, which supports TS <6.1)

tsconfig.base.json — handling the three TS6 breaking changes that affect this repo:

  • types: ["*"]explicit ["node", "jest", "google.maps", "applepayjs"]. TS6 changes the default of types from "auto-enumerate everything in node_modules/@types" to [], which had stopped loading global-only ambients (process/require, jest, google, ApplePaySession) in the webpack build.
  • noUncheckedSideEffectImports: false — TS6 flips this default to true, which errored on .scss side-effect imports (handled by webpack/jest transformers, not TS).
  • ignoreDeprecations: "6.0" — required to suppress a ts-loader build artifact (it emits the moduleResolution=node10 deprecation from its own program init even though our config uses bundler; plain tsc is clean). This is a build-tool quirk that goes away when the toolchain moves off ts-loader for TS7.

.eslintrc.json

  • Disabled @typescript-eslint/no-useless-default-assignment. TS6's sharper inference marks several component props as non-optional, but they are called with undefined at runtime (covered by tests), so the rule's autofix incorrectly strips intentional runtime defaults (e.g. onUnhandledError = noop). Disabling preserves runtime behaviour.

Source (type-only, behaviour-preserving)

  • Removed redundant type conversions (Boolean()/String()/Number()/!!), unnecessary as assertions, and double-awaits inside Promise.all that TS6's stricter inference newly flags.
  • Added eslint-disable @typescript-eslint/naming-convention on snake_case SDK-mirroring keys in a test (matching existing repo convention).

Note: dist/ build artifacts are intentionally not included in this PR (regenerated at release time).

Rollout/Rollback

  • No feature flag / experiment. This is a build-time/type-system change only; there is no runtime behaviour change, no API change, and no DB migration. Emitted JS is functionally identical (TS strips types at compile time).
  • Rollout: standard merge → CI build/lint/test → normal release pipeline. No phased ramp needed.
  • Rollback: straightforward git revert of this single commit (restores typescript@5.8, the tooling versions, and the tsconfig/eslint changes). No data or infra to unwind.
  • Dependency note: this branch was validated against a TS6 build of @bigcommerce/checkout-sdk (typescript-6-upgrade, v1.939.0). package.json still declares ^1.939.0, so once the SDK's TS6 build is published to npm, CI resolves it transparently with no further change here.

Testing

All gates green on TypeScript 6.0.3:

  • Typecheck/Build: npm run build (webpack + ts-loader, production mode) — compiles cleanly, including against the linked local TS6 SDK.
  • Lint: npm run lint0 errors across all 48 projects.
  • Unit tests: full suite passes. core standalone = 215/215 suites, 1360 tests pass. (The only run-many blip is ManageInstrumentsModal.test.tsx, a pre-existing load-induced flake that passes standalone and in isolation — unchanged before/after this work.)
  • E2E (Playwright, REPLAY mode against committed HAR): 41 tests → passed (a couple show as "flaky" from browser-close timing under parallel workers, then pass on retry; 7 skipped). No real failures.
  • Manual store test: loaded the build on a store — checkout renders and functions correctly. The only console output is pre-existing dev-build warnings (React 18 ReactDOM.render legacy API in renderCheckout.tsx, a key prop warning in CheckoutStep, and findDOMNode from react-transition-group/react-media) — none introduced by this change, none touched by this diff, and all stripped in production builds.

How to verify locally

npm ci
npm run lint
npm test
# e2e (note: run the build separately to avoid the prebuild dist-wipe + nx cache trap):
rm -rf packages/test-framework/report
npx nx run core:build --skip-nx-cache
PORT=5005 MODE=REPLAY npx playwright test --project=chromium


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Wide toolchain and @typescript-eslint upgrades affect every package’s compile/lint path; runtime risk is low if emitted JS is equivalent, but a bad override or SDK peer mismatch could break CI until reverted.
> 
> **Overview**
> Upgrades the monorepo from **TypeScript 5.8 to 6.0.3** and bumps **ts-jest** and **ts-loader** so the build and test pipeline accept TS6. **npm overrides** wire internal ESLint packages to the pinned TypeScript version.
> 
> **Compiler config** adapts to TS6 defaults: explicit **`types`** for Node/Jest/Google Maps/Apple Pay globals, **`noUncheckedSideEffectImports: false`** for SCSS side-effect imports, and **`ignoreDeprecations: "6.0"`** for a **ts-loader** deprecation quirk.
> 
> **ESLint** disables **`@typescript-eslint/no-useless-default-assignment`** so intentional runtime defaults on optional props (e.g. `onUnhandledError = noop`) are not stripped.
> 
> Across packages, changes are **type-only / lint-driven**: drop redundant **`Boolean`/`String`/`Number`/`!!`**, unnecessary **`as`** assertions, and double-**`await`** inside **`Promise.all`**; minor import reordering and test **`naming-convention`** disables for SDK snake_case keys. **No intended runtime behavior change.**
> 
> Rollout depends on a compatible **checkout-sdk** build on TS6 (noted in the PR description).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9e4a65bf229b7fc973b6ad71371eaef21f1a5407. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

@bc-0dp
bc-0dp requested review from a team as code owners July 15, 2026 13:44
- Bump typescript 5.8.3 -> 6.0.3, ts-jest -> 29.4.11, ts-loader -> ^9.6.2
- Add scoped npm overrides so internal eslint packages accept TS6 peer range
- tsconfig.base: add ignoreDeprecations '6.0', noUncheckedSideEffectImports false,
  and explicit types [node, jest, google.maps, applepayjs] (TS6 types default is now [])
- eslint: disable no-useless-default-assignment (TS6 infers props non-optional and
  its autofix strips intentional runtime defaults)
- Remove redundant type conversions/assertions and double-awaits surfaced by TS6

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Upgrades the monorepo toolchain to TypeScript 6.0.3, updating related build/test tooling (ts-jest, ts-loader) and adjusting TypeScript/ESLint configuration to account for TS6 default/breaking changes while keeping runtime behavior intended to remain unchanged.

Changes:

  • Bump typescript to 6.0.3 and update ts-jest / ts-loader to versions compatible with TS6.
  • Update tsconfig.base.json for TS6 defaults (explicit types, noUncheckedSideEffectImports: false, and ignoreDeprecations: "6.0").
  • Apply TS6-driven type-only code cleanups across packages and tweak ESLint rules to avoid incorrect autofixes.

Reviewed changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tsconfig.base.json Align compiler options with TS6 defaults and required ambient typings.
packages/utility/src/isExperimentEnabled.ts Remove redundant boolean coercion in feature flag helper.
packages/ui/src/popover/PopoverList.tsx Simplify default getItemProps implementation.
packages/ui/src/icon/CreditCardIcon.tsx Import ordering change.
packages/ui/src/form/PhoneFormField/PhoneInput.tsx Remove redundant string conversion for Formik field value.
packages/test-framework/src/fixture/pageObject/playwright/getAppVersion.ts Rely on type guard to avoid redundant String() conversion.
packages/stripe-integration/src/stripe-ocs/StripeOCSPaymentMethod.tsx Remove redundant boolean coercion in Stripe OCS layout options.
packages/moneris-integration/src/MonerisPaymentMethod.test.tsx Import ordering change.
packages/hosted-widget-integration/src/HostedWidgetPaymentComponent.tsx Remove redundant numeric/boolean coercions in state comparisons/props.
packages/google-pay-integration/src/GooglePayPaymentMethod.tsx Import ordering + remove redundant boolean coercion for feature flag.
packages/error-handling-utils/src/InstrumentDeclinedError/InstrumentDeclinedError.ts Import ordering change.
packages/core/src/app/shipping/stripeUPE/StripeShippingAddressDisplay.tsx Remove unnecessary as Error casts when forwarding caught errors.
packages/core/src/app/shipping/ShippingComponent.test.tsx Remove unnecessary as Cart casts in tests.
packages/core/src/app/payment/PaymentForm.test.tsx Remove unnecessary as FormField cast in tests.
packages/core/src/app/payment/orderExtraFields/OrderExtraFieldsFieldset.test.tsx Remove unnecessary as FormField casts in tests.
packages/core/src/app/payment/cartStockPositionsChangedUtils.test.ts Remove redundant as string casts in tests.
packages/core/src/app/payment/billingForm/PaymentBillingBlock.test.tsx Remove unnecessary as BillingFormValues cast in tests.
packages/core/src/app/order/removeBundledItems.ts Remove redundant String() conversion after typeof === 'string' check.
packages/core/src/app/order/OrderSummaryItems.tsx Simplify boolean conditions around inventory settings flags.
packages/core/src/app/order/getBackorderCount.ts Remove redundant numeric coercion in backorder count calculation.
packages/core/src/app/formFields/getExtraFormFieldsValidationSchema.test.ts Remove unnecessary as FormField casts in tests.
packages/core/src/app/formFields/getCustomFormFieldsValidationSchema.ts Remove redundant boolean coercion in schema field filtering.
packages/core/src/app/customer/LoginForm.tsx Remove redundant Boolean() wrapping in prop expressions.
packages/core/src/app/customer/getSupportedMethods.test.ts Import ordering change.
packages/core/src/app/coupon/OrderSummarySubtotals.test.tsx Remove unnecessary as OrderFee cast in tests.
packages/core/src/app/common/utility/isFloatingLabelEnabled.ts Remove redundant boolean coercion in utility function.
packages/core/src/app/checkout/mapToCheckoutProps.ts Remove redundant boolean coercion for walletButtonsOnTop flag.
packages/core/src/app/billing/hooks/useBilling.ts Remove redundant boolean coercion when checking address presence.
packages/core/src/app/address/googleAutocomplete/googleAutocompleteResult.mock.ts Remove unnecessary as PlaceResult casts in mocks.
packages/core/src/app/address/googleAutocomplete/getGoogleAutocompleteScriptLoader.test.ts Remove as any cast in test setup object.
packages/core/src/app/address/AddressForm.tsx Remove redundant as string cast when calling setFieldValue.
packages/contexts/src/theme/isEnhancedThemeV1Enabled.ts Simplify boolean expression for enhanced theme enablement.
packages/contexts/src/checkout/CheckoutProvider.test.tsx Formatting/import spacing change.
packages/braintree-integration/src/BraintreePaypalPaymentMethod.tsx Import ordering change.
packages/braintree-integration/src/BraintreeAch/hooks/useBraintreeAchValidation.ts Fix Promise.all usage by removing redundant inner awaits.
packages/bigcommerce-payments-utils/src/BigCommercePaymentsPayLaterBanner.test.tsx Add lint disable for snake_case SDK-mirroring keys.
package.json Upgrade TS/tooling versions and add npm overrides for internal ESLint packages.
package-lock.json Lockfile updates reflecting TS/tooling upgrades and dependency graph changes.
.eslintrc.json Disable @typescript-eslint/no-useless-default-assignment due to TS6 inference changes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tsconfig.base.json
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"importHelpers": true,
"ignoreDeprecations": "6.0",

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.

Should we plan to create any follow up tickets to handle these ignored deprecation?

@richapatel1510 richapatel1510 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.

The PR looks good to me, it needs a rebase due to conflict.

@bc-0dp

bc-0dp commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

Yes, the rebase is unavoidable

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.

6 participants