# Reglas de codificación AI para proyectos TypeScript estrictos

> Reglas de AGENTS.md para proyectos TypeScript en modo estricto que eliminan tipos any, imponen patrones de estrechamiento y evitan que los agentes compilen código incorrecto.

**Type:** Rule  
**Tools:** Cursor, Claude Code, Codex, Windsurf  
**Stack:** TypeScript, Next.js  
**Updated:** 2026-06-08

---

Coloca esto en la raíz de tu repositorio como `AGENTS.md`. El modo estricto de TypeScript solo es tan útil como las reglas que eviten que los agentes lo burlen con casts `any` y comentarios `@ts-ignore`.

## AGENTS.md

```md title="AGENTS.md"
# Project Rules — TypeScript Strict

## TypeScript configuration
- `strict: true` is set in `tsconfig.json`. This enables `noImplicitAny`,
  `strictNullChecks`, `strictFunctionTypes`, `strictBindCallApply`,
  `strictPropertyInitialization`, and `noImplicitThis`. Do not disable any of these.
- `noUncheckedIndexedAccess: true` is enabled. Array indexing returns `T | undefined`.
  Always check array access results before using them.
- `exactOptionalPropertyTypes: true` is enabled. Do not assign `undefined` to an
  optional property — omit the property instead.

## Hard rules — no exceptions
- NEVER use `any`. Use `unknown` for values of uncertain type and narrow them
  before use. The single exception is third-party library types that are themselves
  typed as `any` — wrap and re-export with a proper type.
- NEVER use `as T` type assertions unless you add a comment explaining why the
  compiler cannot infer the type and why the assertion is safe. Prefer type guards.
- NEVER use `@ts-ignore` or `@ts-expect-error` without a comment on the same line
  explaining the exact reason. If you find yourself using these, refactor instead.
- NEVER use non-null assertion (`!`) on values that could genuinely be null/undefined
  at runtime. Write an explicit check or use optional chaining (`?.`).
- NEVER widen a type unnecessarily. If a function returns `string`, type it as
  `string` — not `string | undefined` just to avoid a null check.

## Type design conventions
- Model domain errors with discriminated unions, not thrown errors or `null`.
  Return `{ ok: true; value: T } | { ok: false; error: string }` from fallible
  operations instead of relying on catch at the call site.
- Prefer `type` aliases for unions and intersections; use `interface` for object
  shapes that may be extended. Be consistent within a file.
- Generic constraints should be as narrow as possible: `T extends string` instead of
  `T extends unknown` when you only use string operations on `T`.
- Export only what callers need. Keep internal implementation types unexported unless
  there is an explicit reason to expose them.

## Narrowing and runtime validation
- All external data (API responses, form input, `JSON.parse` output, URL params) must
  be validated at the boundary with Zod or a type guard before being used as a typed
  value. Never cast external data with `as MyType` without validation.
- Use `satisfies` to validate object literals against a type without widening:
  `const config = { ... } satisfies Config` instead of `const config: Config = { ... }`
  when you need to preserve literal types.
- Exhaustiveness checks in `switch` statements: add a `default: assertNever(x)` arm
  where `assertNever` is `(x: never) => never` — this catches unhandled union members
  at compile time when the union is extended.

## Definition of done
- `tsc --noEmit` passes with zero errors.
- `grep -r 'as any\|: any\|@ts-ignore\|@ts-expect-error' src/` returns zero results
  (or every hit has an approved justification comment).
- ESLint with `@typescript-eslint/no-explicit-any` and `@typescript-eslint/no-unsafe-*`
  rules enabled passes.
- No `!` non-null assertions on values that come from external data or optional fields.
```

## Por qué estas reglas

- **No `as T` sin un comentario** es la regla más importante después de prohibir `any`. Las aserciones de tipo son la forma principal en que los agentes "arreglan" errores de TypeScript sin realmente arreglarlos — el código compila pero la garantía de tipo en tiempo de ejecución desaparece. Exigir una justificación escrita obliga a los agentes a razonar sobre si la aserción es realmente segura.
- **Validar datos externos en el límite** previene la clase más amplia de errores de tipo en tiempo de ejecución en aplicaciones TypeScript. Los agentes que ven una respuesta de API tipada a menudo confían en la anotación de tipo sin verificar si fue validada al momento de la obtención, produciendo aplicaciones donde los tipos TypeScript son mentiras que compilan limpiamente pero fallan de forma impredecible.

## Buen ajuste

- Bases de código TypeScript de producción con `strict: true` donde la seguridad de tipos es un requisito de calidad de primera clase — especialmente aquellas que manejan datos de usuario, transacciones financieras o integraciones de API externas.

## No es adecuado

- Prototipado rápido o scripts donde la seguridad estricta de tipos añade sobrecarga sin beneficio — usa `strict: false` y un conjunto de reglas más ligero para código desechable.