Best Cursor Settings for TypeScript and React in 2026
Most Cursor tutorials for TypeScript developers start and end at “ask the AI to write a component.” They skip the configuration layer that determines whether those components land in the right style, with the right types, following the right patterns. Unconfigured, Cursor will generate code that compiles but violates your conventions on every other line: default exports when you use named, class components when your codebase is all hooks, any where you’d never allow it.
The gap between out-of-box Cursor and properly configured Cursor for TypeScript/React is about 45 minutes of setup and a permanent shift in suggestion quality. What actually moves the needle: TypeScript version selection, ESLint integration with Cursor’s “Iterate on Lints” feature, Project Rules for consistent AI output, and the @docs setup that makes the AI aware of your exact stack. Pricing claims verified against Cursor’s pricing page on May 9, 2026.
If you’re still evaluating whether Cursor is worth $20/month Pro, read the Cursor IDE Review 2026 first. This guide assumes you’ve already committed to using it.
The TypeScript version problem (fix this first)
Cursor ships with a bundled version of TypeScript for its internal language server. If your project uses a different TypeScript version — which it almost certainly does — the type-checking Cursor shows you and the type-checking your build system runs will diverge. You’ll see different errors in the editor than in CI.
Fix it in one step: open the Command Palette (Ctrl+Shift+P / Cmd+Shift+P), run TypeScript: Select TypeScript Version, and choose Use Workspace Version. This tells Cursor’s language server to use the TypeScript compiler from your node_modules/typescript instead of its own bundled copy.
If “Use Workspace Version” doesn’t appear: your project doesn’t have TypeScript installed as a local dependency. Run npm install -D typescript (or pnpm add -D typescript, bun add -d typescript), then try again.
This single change aligns editor errors with build errors. For teams, commit a .vscode/settings.json that enforces this:
{
"typescript.tsdk": "node_modules/typescript/lib"
}
The tsdk path tells Cursor explicitly where to find the workspace TypeScript. Check this file into version control — every developer on the project gets consistent type-checking without the manual step.
tsconfig.json: what strict actually means for Cursor
Cursor’s AI reads your tsconfig.json to understand your project’s type rules. When strict is disabled, the AI generates looser code — optional chaining where it isn’t needed, implicit any in callbacks, undisciplined null handling. When strict is on, the suggestions tighten noticeably.
A tsconfig.json that gives Cursor the right context for a modern React project:
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Two flags worth singling out:
noUncheckedIndexedAccess: true — makes array and object index access return T | undefined instead of T. This alone eliminates a large class of runtime crashes where code assumes an array element exists. It’s the most common strict flag that teams skip and then regret.
jsx: "react-jsx" — uses the automatic JSX transform. With this, you don’t need import React from 'react' at the top of every file. If the AI still generates that import, add a rule (covered below) to stop it.
The paths block with @/* is worth adding even if you don’t use it immediately. Once configured here, Cursor’s path alias resolution works correctly. Without it, @/components/Button generates import errors that the AI will then try to “fix” by converting back to relative paths.
Extensions: the three you actually need
Cursor’s extension marketplace (Open VSX) has everything VS Code does for TypeScript/React. Three extensions make a real difference; the rest are optional or actively harmful.
1. ESLint (dbaeumer.vscode-eslint) — required if you want Cursor’s “Iterate on Lints” feature to work. This is the most impactful configuration decision for React development (more on this in the next section). Without this extension, the AI can’t see ESLint errors and won’t self-correct violated hooks rules, import ordering, or accessibility issues.
2. Prettier (esbenp.prettier-vscode) — recommended for formatting. Biome is a faster alternative, but as of May 2026, Cursor’s Iterate on Lints only catches tsc and ESLint errors — not Biome diagnostics. If you use Biome for linting, you lose the self-correction loop. Use Biome for formatting only, and keep ESLint for lint rules that Cursor can react to.
3. Tailwind CSS IntelliSense (bradlc.vscode-tailwindcss) — essential if your project uses Tailwind. It provides class name completion, hover documentation, and prevents Cursor from generating non-existent utility classes in JSX. Without it, the AI regularly invents plausible-looking Tailwind classes that don’t exist.
Do not install both Prettier and a formatter bundled inside another extension for the same file types. Conflicting formatters cause “format on save” to produce different output on every save and confuse the AI about your actual style.
Workspace settings: the complete .vscode/settings.json
A .vscode/settings.json that works for TypeScript/React projects with ESLint and Prettier:
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.preferences.importModuleSpecifier": "non-relative",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
}
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
}
},
"eslint.validate": ["typescript", "typescriptreact"],
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.preferences.preferTypeOnlyAutoImports": true
}
Key decisions here:
"source.organizeImports": "never"— disables VS Code’s built-in import sorter, which conflicts with ESLint’s import ordering rules and produces different results. Let ESLint or Prettier handle import organization consistently."typescript.updateImportsOnFileMove.enabled": "always"— automatically updates import paths when you rename or move files. This prevents the AI from seeing stale import paths that don’t exist."typescript.preferences.preferTypeOnlyAutoImports": true— auto-imports types withimport type, keeping runtime bundle size down and satisfying the@typescript-eslint/consistent-type-importsrule.
Commit this file. It’s not personal preference — it’s project tooling, the same as package.json.
Iterate on Lints: the React-specific killer feature
This is the Cursor setting that React developers get the most value from and the one least covered in general Cursor guides.
How to enable it: Open Cursor Settings (Ctrl+Shift+J / Cmd+Shift+J) → Chat → toggle on Iterate on Lints.
What it does: After Agent mode makes code changes, Cursor waits for ESLint and TypeScript errors to surface in the editor, reads them, and automatically attempts to fix them — without you asking. It runs in a loop until errors clear or it hits a maximum retry count.
For React specifically, this catches things the AI gets wrong constantly:
- Hooks rules violations — calling
useStateconditionally,useEffectwith wrong dependency arrays,useMemowith stale dependencies. ESLint’sreact-hooksplugin catches all of these, and Iterate on Lints fixes them automatically. - TypeScript type mismatches — wrong prop types, missing generic parameters, incorrect event handler types (
React.ChangeEvent<HTMLInputElement>vsReact.SyntheticEvent). - Accessibility issues — if you run
eslint-plugin-jsx-a11y, Cursor will self-correct missingaltattributes, incorrect ARIA roles, and unlabeled form controls.
For this to work, your eslint.config.js (or .eslintrc) needs eslint-plugin-react-hooks configured. A minimal flat-config ESLint setup for a React TypeScript project:
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
},
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
}
);
One important limitation: Cursor’s Iterate on Lints reads tsc and ESLint diagnostics. It does not read Biome diagnostics, even though Biome errors appear as red squiggly lines in the editor. If your team uses Biome as your linter, self-correction won’t fire for those errors — you’ll need to run biome check --apply manually in the terminal.
Project Rules: the highest-ROI configuration
Project Rules are the most underused Cursor feature for TypeScript/React teams. A focused rules file eliminates the most common AI mistakes in your codebase — no model upgrade required.
Create .cursor/rules/typescript.mdc:
---
description: TypeScript coding standards for this project
alwaysApply: true
globs: ["**/*.ts", "**/*.tsx"]
---
You are helping with a TypeScript project. Follow these rules strictly:
**Types**: Never use `any`. Use `unknown` for values of unknown type, then narrow.
Never use type assertions (`as`) on data from APIs, user input, or external sources.
Use Zod schemas for runtime validation of external data.
**Imports**: Use `import type` for type-only imports. Group: external packages,
then internal paths. Keep imports sorted alphabetically within groups.
**Null handling**: Use optional chaining (`?.`) and nullish coalescing (`??`).
Never use `!` non-null assertion unless absolutely necessary — add a comment
explaining why.
**Functions**: Prefer `const` arrow functions for utilities. Avoid `function`
declarations at module level except for React components (use `function` keyword
for components — it reads more clearly in stack traces).
**Enums**: Do not use TypeScript enums. Use `const` objects with `as const` and
derive the union type: `type Status = typeof STATUS[keyof typeof STATUS]`.
**Generics**: Use descriptive generic names (`TData`, `TError`) rather than
single-letter (`T`, `E`) when the generic has semantic meaning.
Create .cursor/rules/react.mdc:
---
description: React component and hooks standards for this project
alwaysApply: true
globs: ["**/*.tsx", "src/hooks/**/*.ts"]
---
You are helping with a React TypeScript project. Follow these rules:
**Components**: Use function declarations, not arrow functions, for component
definitions. Use named exports, not default exports. Props are typed with
interfaces, not inline type literals.
**JSX**: Do not add `import React from 'react'` — the automatic JSX transform
handles this. Do not use inline styles; use Tailwind CSS utility classes.
**Hooks**: Custom hooks go in `src/hooks/` and are prefixed with `use`.
Never call hooks conditionally. Always include all values used inside a
`useEffect` or `useCallback` in the dependency array.
**State**: Use `useState` for local UI state. Use React Query (or the project's
data-fetching library) for server state — do not fetch in `useEffect` unless
there is no alternative.
**Events**: Type event handlers explicitly:
- `onChange`: `React.ChangeEvent<HTMLInputElement>`
- `onSubmit`: `React.FormEvent<HTMLFormElement>`
- `onClick`: `React.MouseEvent<HTMLButtonElement>`
**Memoization**: Apply `React.memo` to expensive list items, not wholesale.
Use `useCallback` on handlers passed as props to memoized children. Do not
memoize everything — it adds overhead and rarely helps.
**Error handling**: Every page-level component tree has an Error Boundary.
For async operations, handle loading and error states explicitly — no silent
failures.
For Next.js projects, add a scoped rules file that only fires in the right directories:
---
description: Next.js App Router conventions
alwaysApply: false
globs: ["app/**/*.tsx", "app/**/*.ts"]
---
This project uses Next.js App Router. Follow these rules:
**Server vs Client**: Components in `app/` are Server Components by default.
Add `'use client'` only when the component uses hooks, browser APIs, or event
listeners. Do not add `'use client'` by default.
**Data fetching**: Fetch in Server Components using async/await directly. Use
`fetch()` with Next.js cache options (`{ next: { revalidate: 3600 } }`).
Do not use React Query or SWR in Server Components.
**Routing**: Use `useRouter` from `next/navigation`, not `next/router`.
Use `Link` from `next/link` for internal navigation.
**Images**: Use `next/image` for all `<img>` tags. Always provide `width`,
`height`, and `alt`. For dynamically sized images, use `fill` with a positioned
parent container.
**Metadata**: Export a `metadata` object from page files, not `<Head>` tags.
The glob scoping matters: the Next.js rules only fire when you’re in the app/ directory. They don’t bloat prompts when you’re editing a utility or a shared component.
@Docs: making the AI aware of your exact stack
Cursor can index external documentation and make it available in chat via @docs. For TypeScript/React projects, add these under Settings > Features > Docs:
https://react.dev— the current React documentation (not the old reactjs.org)https://www.typescriptlang.org/docs/— the TypeScript handbookhttps://tanstack.com/query/latest/docs— if you use React Query- Your UI library’s docs (Shadcn, Radix, Material UI)
Once indexed, prefix your prompt with @React or @TypeScript to ground the AI’s response in current documentation instead of its training data. This matters because React and TypeScript move fast — React 19 hooks, the TypeScript 5.x satisfies operator, and other features from the past year may not be reliably in the AI’s training data.
Model selection for TypeScript and React
Cursor’s model lineup as of May 2026 includes Composer 2 (the default, Cursor-built), GPT-5.4, Claude Opus 4.6, and Gemini 3 Pro. The choice matters for TypeScript work in specific ways:
Composer 2 — best for iterative edits: refactoring a component, adding a prop, moving state up. Fastest response, lowest per-request cost, and well-calibrated for applying clean diffs. Use this as your default.
Claude Opus 4.6 — best for complex type problems: designing a generic utility type, debugging a type error you don’t understand, writing a complex Zod schema. Slower and more expensive request-wise, but produces stronger reasoning about type relationships. When you’re stuck on a hard TypeScript problem, switching to Opus is worth the wait.
GPT-5.4 — strongest benchmark performance on coding tasks overall (88.0% on Aider’s polyglot benchmark). Good for one-shot large component generation or when Composer 2 produces something semantically off and you want a second opinion.
For most TypeScript/React work: Composer 2 by default, Opus 4.6 for hard type problems, GPT-5.4 as a tiebreaker.
The settings that move the needle most
If you’re skimming and want the short version, these four changes have the highest impact in order:
1. Select workspace TypeScript. TypeScript: Select TypeScript Version → Use Workspace Version. Without this, the AI’s type understanding diverges from your build. Every other setting is undermined by editor/build mismatch.
2. Enable Iterate on Lints with react-hooks ESLint. This converts the AI from “generates code that might violate hooks rules” to “generates code and self-corrects any hooks violations automatically.” The improvement on multi-component refactors is dramatic. You stop being the one who runs ESLint and feeds the errors back manually.
3. Write Project Rules files. A 40-line react.mdc that specifies component style, export convention, and hooks patterns eliminates the most common AI mistakes in your codebase. The ROI on writing this file is higher than any model upgrade.
4. Add your UI library docs. If you’re using Shadcn, Radix, or another library, add its documentation via Settings > Features > Docs and reference it with @YourLibrary in prompts. The AI’s training data for new versions of rapidly-evolving libraries is often stale by 6–12 months; the indexed docs fix that immediately.
Honest take
TypeScript/React is Cursor’s strongest surface — the language server, type-aware completions, and multi-file refactoring capabilities are genuinely good out of the box. The gap between configured and unconfigured is smaller here than it is for Python. But it’s still real.
The TypeScript version selection is non-negotiable. The Project Rules investment pays off fast — most teams find within a week that they’ve stopped correcting the same category of AI mistakes they were correcting before writing the rules. “Iterate on Lints” with the react-hooks plugin running is the closest thing to a free lunch in Cursor configuration: it’s a one-time toggle that permanently improves a recurring annoyance.
The one thing teams consistently underdo: scoping rules. A single monolithic .cursorrules at the project root works, but it’s blunt. Splitting into typescript.mdc (always), react.mdc (tsx files), and nextjs.mdc (app/ directory) keeps each rules file focused and readable — which keeps the AI’s adherence high.
For the hardware side — if you’re considering running a local model alongside Cursor to reduce API costs during heavy component generation sessions, the GPU and RAM requirements depend heavily on model size. The full analysis is on the runaihome.com side of this network: Local LLM Hardware Guide.
Sources
- Cursor Pricing — cursor.com/pricing — Hobby (free), Pro ($20/mo), Pro+ ($60/mo), Ultra ($200/mo), Teams ($40/user/mo). Verified May 9, 2026.
- Cursor Rules Documentation — cursor.com/docs/context/rules — Project Rules, User Rules, .mdc file format, glob patterns, alwaysApply frontmatter.
- Cursor JavaScript & TypeScript Guide — cursor.com/docs/guides/languages/javascript — Language-specific Cursor configuration and TypeScript settings.
- Builder.io: The Perfect Cursor Setup for React and Next.js — builder.io/blog/cursor-ai-tips-react-nextjs — @Docs integration, ESLint Iterate on Lints, model selection for React projects.
- Cursor Rules for TypeScript Engineers — stevekinney.com/writing/cursor-rules-typescript — TypeScript-specific rule patterns: no any, Zod for external data, no enums, import grouping.
- Cursor Community: Iterate on Lint Errors — forum.cursor.com — How the Iterate on Lints loop works, ESLint vs Biome limitation, React hooks self-correction examples.
- Aider Polyglot Benchmark — aider.chat/docs/leaderboards/ — GPT-5.4 at 88.0% on multi-language coding tasks; comparative model performance reference.
- awesome-cursorrules: TypeScript React templates — github.com/PatrickJS/awesome-cursorrules — Community-maintained .cursorrules templates for TypeScript and React projects.
Last updated May 9, 2026. Cursor updates settings and models frequently — verify current behavior before building team workflows around specific features.
Was this article helpful?
Thanks for the feedback — it helps improve future articles.