# How to Enforce Strict Typing with Cursor

- Tool: Cursor
- Difficulty: Beginner
- Time required: 10-15 min
- Compatibility: Cursor Free+, NestJS/TypeScript projects
- Last updated: March 2026

## TL;DR

Cursor often generates loosely typed NestJS code with 'any' types, partial interfaces, and missing decorators. By adding project rules that enforce strict TypeScript mode, referencing your existing entity files with @file, and prompting with explicit typing requirements, you can ensure Cursor generates properly decorated NestJS classes with full type safety including DTOs, entities, and validation pipes.

## Enforcing strict typing in Cursor-generated NestJS code

NestJS relies heavily on TypeScript decorators, class-validator, and class-transformer for type-safe APIs. Cursor can generate syntactically correct NestJS code that lacks proper decorators, uses any types, or skips validation. This tutorial configures Cursor to produce fully typed, decorated NestJS code that matches your project's standards.

## Before you start

- Cursor installed with a NestJS project open
- TypeScript strict mode enabled in tsconfig.json
- class-validator and class-transformer installed
- Familiarity with NestJS decorators and modules

## Step-by-step guide

### 1. Create a NestJS strict typing rule

Add a project rule that enforces TypeScript strict mode conventions specifically for NestJS patterns. Include requirements for decorators, DTOs, entities, and service methods. NestJS-specific patterns need explicit rules because Cursor may generate plain TypeScript instead of decorated classes.

```
---
description: Enforce strict typing in NestJS code
globs: "*.ts"
alwaysApply: true
---

# NestJS Strict Typing Rules

## TypeScript:
- NEVER use 'any' type — use 'unknown' and narrow, or define proper types
- NEVER use type assertions (as) unless narrowing from unknown
- ALWAYS use explicit return types on all public methods
- ALWAYS enable strict mode patterns: strictNullChecks, noImplicitAny

## DTOs:
- ALWAYS use class-validator decorators on every DTO property
- ALWAYS use class-transformer @Type() for nested objects
- ALWAYS use @ApiProperty() from @nestjs/swagger on DTO properties
- ALWAYS create separate CreateDto, UpdateDto (with PartialType), ResponseDto
- Use readonly properties in response DTOs

## Entities:
- ALWAYS use TypeORM decorators: @Entity, @Column, @PrimaryGeneratedColumn
- ALWAYS specify column types explicitly: @Column({ type: 'varchar', length: 255 })
- ALWAYS define relations with explicit types and decorators

## Services:
- ALWAYS define return types as Promise<EntityType> or Promise<EntityType[]>
- ALWAYS handle null returns explicitly with proper error throwing
- Use custom exception classes extending HttpException
```

**Expected result:** Cursor generates NestJS code with full TypeScript strict typing, class-validator decorators, and explicit return types.

### 2. Reference existing entities as patterns for new code

When asking Cursor to generate a new module, reference an existing well-typed entity with @file. Cursor pattern-matches against the referenced file, producing new code that follows the same decoration and typing conventions.

```
@nestjs-typing.mdc @src/users/entities/user.entity.ts

Create a complete Product module following the exact same patterns
as the User entity. Include:
1. product.entity.ts — TypeORM entity with proper column types
2. create-product.dto.ts — with class-validator decorators
3. update-product.dto.ts — using PartialType(CreateProductDto)
4. product-response.dto.ts — readonly response with @ApiProperty
5. products.service.ts — with explicit Promise return types
6. products.controller.ts — with full Swagger decorators

The Product has: id (uuid), name (string 255), price (decimal),
category (string 100), isActive (boolean), createdAt, updatedAt.
```

> Pro tip: Always reference an existing file that follows your conventions. Cursor's pattern matching from real project files is more reliable than rules alone for complex decorator patterns.

**Expected result:** Cursor generates six files matching the User entity patterns with full TypeORM and class-validator decorators.

### 3. Generate a type-safe DTO with validation using Cmd+K

Open a new file, type a basic class skeleton, select it, and press Cmd+K. Ask Cursor to add all necessary decorators and validation. This is faster than generating from scratch when you know the structure you want.

```
Add strict typing, class-validator decorators, and @ApiProperty to this
NestJS DTO. Every string needs @IsString() and @MaxLength().
Every number needs @IsNumber() and @Min/@Max.
Optional fields need @IsOptional(). Nested objects need @ValidateNested()
and @Type(). Add @ApiProperty with description and example for each field.
```

**Expected result:** Cursor adds class-validator decorators, @ApiProperty with descriptions, and proper type constraints to every property.

### 4. Audit existing code for type safety gaps

Use Cursor Chat with @codebase to scan your NestJS project for type safety issues. This catches any types, missing decorators, and implicit return types that could cause runtime errors or Swagger documentation gaps.

```
@nestjs-typing.mdc @codebase

Audit this NestJS project for type safety issues. Find and list:
1. Any use of 'any' type in services, controllers, or DTOs
2. DTO properties missing class-validator decorators
3. Service methods without explicit Promise return types
4. Entity columns without explicit type definitions
5. Controllers missing @ApiResponse decorators

For each issue, show the file, line, and the corrected version.
```

**Expected result:** Cursor lists all type safety gaps in your NestJS project with specific file locations and corrected code for each.

### 5. Set up a custom command for DTO generation

Create a reusable Cursor custom command that generates fully typed DTOs on demand. Save this in .cursor/commands/ so any team member can type /dto in Chat to generate a new DTO set following your standards.

```
---
description: Generate a type-safe NestJS DTO set
---

Generate a complete set of NestJS DTOs for the entity described by the user.

Follow these rules:
1. CreateDto — all required fields with class-validator decorators
2. UpdateDto — extends PartialType(CreateDto)
3. ResponseDto — readonly fields with @Exclude() for sensitive data
4. QueryDto — optional filter parameters with @IsOptional()

Every property must have:
- @ApiProperty() with description and example
- Appropriate class-validator decorator
- Explicit TypeScript type (never any)

Reference @nestjs-typing.mdc for full conventions.
```

**Expected result:** Team members can type /dto in Cursor Chat followed by an entity description to generate a complete DTO set.

## Complete code example

File: `src/products/dto/create-product.dto.ts`

```typescript
import { ApiProperty } from '@nestjs/swagger';
import {
  IsString,
  IsNumber,
  IsBoolean,
  IsOptional,
  MaxLength,
  Min,
  Max,
  IsNotEmpty,
} from 'class-validator';

export class CreateProductDto {
  @ApiProperty({ description: 'Product name', example: 'Wireless Keyboard' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  readonly name: string;

  @ApiProperty({ description: 'Price in USD', example: 49.99 })
  @IsNumber({ maxDecimalPlaces: 2 })
  @Min(0)
  @Max(999999.99)
  readonly price: number;

  @ApiProperty({ description: 'Product category', example: 'Electronics' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(100)
  readonly category: string;

  @ApiProperty({ description: 'Whether product is active', example: true, required: false })
  @IsOptional()
  @IsBoolean()
  readonly isActive?: boolean;

  @ApiProperty({ description: 'Product description', example: 'A compact wireless keyboard', required: false })
  @IsOptional()
  @IsString()
  @MaxLength(2000)
  readonly description?: string;
}
```

## Common mistakes

- **Not specifying NestJS-specific decorators in rules** — Cursor may generate plain TypeScript classes without @Entity, @Column, or class-validator decorators since generic TypeScript rules do not cover framework-specific patterns. Fix: Create NestJS-specific rules that list every required decorator pattern for entities, DTOs, and controllers.
- **Using interface DTOs instead of class DTOs** — TypeScript interfaces are erased at runtime, so class-validator and class-transformer cannot validate or transform them. NestJS validation pipes require classes. Fix: Add to your rules: ALWAYS use classes for DTOs, never interfaces. Interfaces do not work with NestJS validation pipes.
- **Accepting Cursor output with 'any' return types on service methods** — Any types bypass TypeScript's type checking, allowing incorrect data shapes to flow through your application without compile-time errors. Fix: Add a rule mandating explicit Promise<EntityType> return types. Use the audit prompt periodically to catch any types that slip through.

## Best practices

- Reference an existing well-typed entity file with @file when generating new modules
- Create separate Create, Update, Response, and Query DTOs for each entity
- Use PartialType and PickType from @nestjs/swagger for DTO composition
- Add @ApiProperty to every DTO field for automatic Swagger documentation
- Create custom commands in .cursor/commands/ for repeatable DTO generation
- Audit for 'any' types periodically using @codebase searches
- Enable TypeScript strict mode in tsconfig.json to complement Cursor rules

## Frequently asked questions

### Why does Cursor use 'any' even when strict mode is enabled?

TypeScript strict mode is a compiler setting, but Cursor does not read tsconfig.json during generation. You must explicitly tell Cursor in your rules to never use any and always use explicit types.

### Should I use interfaces or classes for NestJS DTOs?

Always use classes. NestJS validation pipes and class-transformer require classes because TypeScript interfaces are erased at runtime and cannot be validated.

### How do I handle nested object validation?

Use @ValidateNested() from class-validator and @Type(() => NestedDto) from class-transformer. Add this pattern to your rules file with an example.

### Can Cursor generate TypeORM migrations from entities?

Cursor can generate migration files if you provide the entity as context, but TypeORM's migration:generate CLI command is more reliable since it diffs against the actual database schema.

### What about Prisma instead of TypeORM?

If using Prisma, update your rules to reference Prisma schema files and generated types. Cursor can generate NestJS services that use Prisma Client with full type safety from the generated types.

### Can RapidDev help set up type-safe NestJS architecture?

Yes. RapidDev helps teams design NestJS module structures with strict typing, validation, and Swagger documentation, and configures Cursor rules to maintain these standards across the team.

---

Source: https://www.rapidevelopers.com/cursor-tutorial/how-to-refine-cursor-ai-so-it-produces-strictly-typed-model-classes-in-a-nestjs-domain-layer
© RapidDev — https://www.rapidevelopers.com/cursor-tutorial/how-to-refine-cursor-ai-so-it-produces-strictly-typed-model-classes-in-a-nestjs-domain-layer
