Skip to content

feat: finalize TypeScript migration — strict mode and linting#30

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1776397237-finalize-ts-migration
Open

feat: finalize TypeScript migration — strict mode and linting#30
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1776397237-finalize-ts-migration

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented Apr 17, 2026

Summary

Complete JS-to-TS migration of the entire Next.js 12 ecommerce app. Every source file in lib/, context/, components/, pages/, and pages/api/ has been renamed from .js/.jsx to .ts/.tsx with full strict-mode type annotations.

Key changes:

  • tsconfig.json: Created with "strict": true, "allowJs": false; includes "ignoreDeprecations": "6.0" because Next.js 12 forces moduleResolution: node which TS 6.0 deprecates.
  • types/index.ts: Shared interfaces (SanityProduct, CartItem, SanityBanner, StateContextType) inferred from usage patterns in the codebase (not from a Sanity schema file).
  • .babelrc: Added @babel/preset-typescript — required because the project uses a custom Babel config that disables SWC, so Babel must understand TS syntax.
  • .eslintrc.json: Extended with @typescript-eslint/recommended, parser, and plugin.
  • yarn.lock removed: Standardized on npm / package-lock.json since all dependency changes were made via npm. The stale yarn.lock was causing Next.js 12's type-check step to fail.
  • @types/react@17.0.39: Pinned to this specific older version for compatibility with Node.js 22 + Next.js 12's require.resolve package detection.

Incidental bug fixes made during migration

These were discovered because strict TS caught them or because the original code had runtime issues:

File Change Why
index.tsx (HeroBanner/FooterBanner) Conditional rendering instead of {} as SanityBanner fallback Prevents runtime crash when bannerData is empty — the previous cast silenced TS but passed an empty object that would throw on property access
Cart.tsx:27 response.statusCoderesponse.status fetch Response uses .status, not .statusCode
Cart.tsx:32 stripe.redirectToCheckout(…)stripe?.redirectToCheckout(…) getStripe() can return null
Cart.tsx:78 Removed onClick="" from quantity <span> Was a no-op string, not a valid handler
StateContext.tsx onAdd Added missing return cartProduct in .map() else-branch Original silently returned undefined for non-matching items
StateContext.tsx onAdd product.quantity = quantity → spread { ...product, quantity } Avoids mutating the input parameter
StateContext.tsx onRemove Added null guard on foundProduct Prevents crash if item not found
All image sources urlFor(x)urlFor(x).url() Returns a string URL instead of an ImageUrlBuilder object

Review & Testing Checklist for Human

  • Verify the Sanity types match reality: SanityProduct, CartItem, and SanityBanner in types/index.ts were inferred from code usage, not from a Sanity schema. Fields like SanityImage.asset._ref, SanitySlug, and all banner fields should be cross-checked against the actual Sanity studio schema.
  • Review behavioral changes in StateContext.tsx: The onAdd map fix (adding return cartProduct) and the spread-instead-of-mutate change alter runtime behavior — confirm cart add/update still works correctly.
  • Confirm urlFor(...).url() renders images correctly: Every urlFor() call now chains .url(). Verify images load on the homepage, product pages, and cart.
  • yarn.lock removal: If your team uses yarn, this may be unwanted. The removal was necessary because the stale lockfile broke next build's type detection.
  • Stripe API version cast in pages/api/stripe.ts: '2020-08-27' as Stripe.LatestApiVersion is a type assertion that papers over a version mismatch — verify this is acceptable for your Stripe integration.

Recommended test plan: Run npm run dev, visit the homepage, open a product detail page, add items to cart, and attempt checkout to verify the migration didn't break any runtime behavior.

Notes

  • All pre-existing lint warnings (img vs next/image, missing passHref, missing alt text, useEffect deps) are unchanged — they are not new to this PR.
  • @typescript-eslint is pinned to v5.x for compatibility with the project's ESLint 8.13.
  • Verification results: npx tsc --noEmit (0 errors), npm run build (success), npm run lint (success, warnings only), npm run dev (starts cleanly).

Link to Devin session: https://app.devin.ai/sessions/b5bb27e2f3644a37b6945e3b242e9b3e
Requested by: @WesternConcrete


Open with Devin

- Migrate all JS/JSX files to TS/TSX across lib/, context/, components/, pages/
- Create types/index.ts with SanityProduct, CartItem, SanityBanner interfaces
- Add tsconfig.json with strict: true and allowJs: false
- Install and configure @typescript-eslint/parser and @typescript-eslint/eslint-plugin
- Update .eslintrc.json with TypeScript parser config
- Add @babel/preset-typescript to .babelrc for build compatibility
- Remove stale yarn.lock, standardize on npm with package-lock.json
- All verifications pass: tsc --noEmit (0 errors), npm run build, npm run lint, npm run dev

Co-Authored-By: Wes Convery <2wconvery@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Address Devin Review feedback — conditionally render HeroBanner and
FooterBanner only when bannerData is non-empty instead of using an
unsafe type assertion that would cause runtime crashes.

Co-Authored-By: Wes Convery <2wconvery@gmail.com>
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