Back to Guides
Tool-Specific

Cursor Rules for TypeScript

TypeScript without rules gives you TypeScript with any everywhere. Here is the .cursor/rules setup that makes Cursor write strict, idiomatic TypeScript from the first line.

Last updated: 2026-07-01

The TypeScript mistakes Cursor makes without rules

Left to defaults, Cursor writes valid-but-weak TypeScript: it uses any when types get complex, writes type instead of interface for component props, invents inconsistent generic names, and rarely adds return type annotations. None of this breaks compilation, but it erodes the value of TypeScript entirely.

Key TypeScript conventions to encode

The most impactful rules are: strict mode on (catches nullability bugs), no any without a comment explaining why, interfaces for object shapes and component props, type aliases for unions and utility types, consistent generic naming (T, TData, TResponse), and Zod for runtime validation at API boundaries. Encode all of these explicitly -Cursor won't infer them from your tsconfig alone.

Ready-to-use TypeScript rules

Place this at .cursor/rules/typescript.mdc in your project root.

.cursor/rules/typescript.mdc
---
description: TypeScript conventions for this project
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: true
---

# TypeScript Rules

## Strictness
- tsconfig strict: true is enabled. Never disable strictNullChecks.
- Never use `any`. If unavoidable, add: // eslint-disable-next-line @typescript-eslint/no-explicit-any with a comment explaining why.
- Use `unknown` for values of unknown type, then narrow with type guards.

## Types vs Interfaces
- Use `interface` for object shapes, component props, and API response structures.
- Use `type` for union types, intersection types, and utility type aliases.
- Do NOT use enums. Prefer union string literals: type Status = 'idle' | 'loading' | 'error' | 'success'

## Generics
- Name generics: T (general), TData (data payloads), TResponse (API responses), TProps (component props).
- Avoid single-letter generics beyond T in complex signatures.

## Zod
- All external data (API responses, form inputs, env vars) must be validated with a Zod schema at the boundary.
- Infer TypeScript types from Zod: type User = z.infer<typeof UserSchema>. Never duplicate the type manually.

## Return Types
- Always annotate return types on exported functions and React components.
- Exception: simple arrow function callbacks where the type is obvious from context.

## Naming
- Boolean variables: is/has/can/should prefix. (isLoading, hasError, canSubmit)
- Event handlers: handle prefix. (handleSubmit, handleChange)
- Custom hooks: use prefix. (useAuth, useDebounce)

Combining with ESLint

Your Cursor rules and your ESLint config should agree. If your .eslintrc bans any, your cursor rules should too. When they conflict, Cursor will follow its rules file -but your CI will catch the violations anyway. Consistency between the two avoids confusion.

Generate TypeScript conventions for your exact stack

standarx generates cursor rules and CLAUDE.md files tailored to TypeScript, including the specific libraries and patterns your project uses.

Generate my rules file