ANTIGRAVITY LABJP
Articles/Editor View
Editor View/2026-04-14Intermediate

Making Antigravity Write Type-Safe TypeScript — Eliminating `any` with Prompt Design and Rules Files

Stop `any` from creeping into AI-generated TypeScript. A practical guide to Rules file configuration and prompt design that keeps your codebase type-safe — even when Antigravity is doing the heavy lifting.

typescript26type-safety3prompt-engineering7ruleseditor31

Ask Antigravity to add a feature, and suddenly your codebase has three new any types. Ask it to fix a TypeScript error, and it slaps on as any and calls it done.

If this sounds familiar, you're not dealing with a flaw in Antigravity — you're dealing with a calibration problem. AI coding assistants are optimized to produce working code as fast as possible, and any is the fastest way to silence a type error. Without explicit constraints, that's the path Antigravity will take.

This guide covers two complementary approaches: configuring Rules files so that type-safe behavior is the default, and designing prompts that give Antigravity the context it needs to infer types correctly rather than reaching for any.

Why Antigravity Reaches for any

The pattern isn't random. Antigravity generates any most often in three situations:

Missing context: When the function's input and output types aren't visible in the conversation, Antigravity can't infer them. Asking "write a function that calls this API" without providing the response type schema almost always yields an any-typed return value.

Error suppression requests: Telling Antigravity to "fix the TypeScript errors" without specifying how invites shortcuts. Wrapping the problematic line in as any resolves the error with minimal code change — exactly the kind of solution an AI optimizing for brevity might choose.

Complex generic types: When a library's type signature involves deeply nested generics, Antigravity may cast to any to sidestep the complexity rather than correctly parameterizing the type.

All three are avoidable with the right setup.

Enforcing Type Safety Through Rules Files

A .antigravity/rules/typescript.md file applies constraints globally across every session in your project. Here's a practical starting configuration:

# TypeScript Type Safety Rules (Required)
 
## Strictly Prohibited
- The `any` type (use `unknown` + type guards instead)
- `as any` casts
- `@ts-ignore` and `@ts-expect-error` without an explanatory comment
- Excessive non-null assertions `\!` (only allowed after explicit null checks)
 
## Required Patterns
- Validate external API responses using `unknown` + Zod schemas
- Use generics wherever a function operates on multiple types
- Prefer type inference over redundant explicit annotations
- Resolve type errors by fixing the type definition or adding a type guard — never by widening to `any`
 
## Error Resolution Priority
When encountering a TypeScript error:
1. Fix the underlying type definition
2. Add a type guard function
3. Use a justified type assertion (with an inline comment explaining why)

With this in place, Antigravity will pause before generating any and look for a typed alternative. For a deeper look at structuring Rules files across a project, see the Antigravity Custom Rules & Project Configuration Mastery Guide.

Prompt Design: Giving Antigravity the Types It Needs

Rules files set the constraint. Prompt design provides the context. Together, they eliminate almost all cases of unintended any.

Contrast: vague vs. context-rich prompts

❌ Vague prompt:
"Write a fetchUser function"

✅ Context-rich prompt:
"Write a fetchUser function with these constraints:
 - Return type: Promise<User>
 - Handle API errors using a Result<User, ApiError> pattern
 - Validate the response with the Zod schema in @src/schemas/user.ts
 - The User type is defined in @src/types/user.ts"

The vague version leaves Antigravity guessing about the User type, so it defaults to any. The second version provides the type contracts upfront — Antigravity no longer needs to guess.

Using @mentions to share type definitions

The most reliable way to ground Antigravity in your type system is to pass your type files directly:

"Referring to @src/types/user.ts and @src/types/api.ts,
implement a userService module that uses these types throughout"

For broader prompt strategies, the Antigravity Prompt Engineering Guide covers the full pattern in detail.

Before and After: A Real Example

The same feature request, with and without proper setup:

Scenario: Fetch user data from a REST API endpoint.

Before (no context, no Rules)

// Antigravity-generated code — problematic
async function fetchUser(id: string): Promise<any> {
  const response = await fetch(`/api/users/${id}`);
  const data = await response.json();
  return data; // typed as any — type safety lost downstream
}
 
// The caller inherits the any type
const user = await fetchUser("123");
console.log(user.naem); // typo — no compiler error

After (Rules applied + context-rich prompt)

// Generated with @src/schemas/user.ts and @src/types/api.ts in context
import { z } from "zod";
 
const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  createdAt: z.string().datetime(),
});
 
type User = z.infer<typeof UserSchema>;
 
type ApiError = {
  code: string;
  message: string;
};
 
type Result<T, E> = { success: true; data: T } | { success: false; error: E };
 
async function fetchUser(id: string): Promise<Result<User, ApiError>> {
  try {
    const response = await fetch(`/api/users/${id}`);
 
    if (\!response.ok) {
      const error: ApiError = await response.json();
      return { success: false, error };
    }
 
    // Receive as unknown, validate with Zod
    const rawData: unknown = await response.json();
    const parsed = UserSchema.safeParse(rawData);
 
    if (\!parsed.success) {
      return {
        success: false,
        error: { code: "PARSE_ERROR", message: parsed.error.message },
      };
    }
 
    return { success: true, data: parsed.data };
  } catch (e) {
    return {
      success: false,
      error: { code: "NETWORK_ERROR", message: String(e) },
    };
  }
}
 
// Caller benefits from full type safety
const result = await fetchUser("123");
if (result.success) {
  console.log(result.data.name); // autocomplete works
  // console.log(result.data.naem); // compile error ✅
}

With Rules and a context-rich prompt, Antigravity generates the Zod schema, Result type, and full error handling as a unit. The type safety propagates outward to every call site automatically.

Common Pitfalls

A few issues that come up frequently in real projects:

tsconfig.json without strict: true

Rules file constraints work best when the compiler enforces them too. Without "strict": true in tsconfig.json, Antigravity calibrates its output to the actual compiler settings — not to your ideal. Add the strictest settings your project can handle:

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true
  }
}

Including @tsconfig.json in your prompts signals to Antigravity to respect these settings when generating code.

Prompts that implicitly invite any

A prompt like "just make the TypeScript errors go away" is an invitation to use any. Be explicit about the constraint:

❌ "Fix all the TypeScript errors however you can"
✅ "Fix the TypeScript errors without using any, as any, or @ts-ignore"

Under-specified generic functions

When writing utility functions, Antigravity sometimes hardcodes a specific type where a generic would be more appropriate. Adding "implement this as a generic function" or "use generics so this works with any type T" explicitly surfaces that requirement.

Where to Go From Here

The most effective change you can make today is adding a single-line any prohibition to .antigravity/rules/typescript.md and watching the next session's output shift. The difference in code quality is usually immediate.

For a broader view of how TypeScript type design interacts with Antigravity across a full-stack project, the TypeScript + Antigravity Type-Safe Full-Stack Development Guide is the natural next step.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Editor View2026-05-05
TypeScript Path Aliases Not Working in Antigravity: Complete Fix Guide
Fix TypeScript @/ path aliases that aren't resolving in Antigravity. From tsconfig.json paths config to workspace settings and AI suggestion rules, this guide covers every step to eliminate TS2307 errors.
Editor View2026-05-04
When ESLint and TypeScript Squiggles Disappear in Antigravity: A 5-Point Diagnostic
When the red squiggles in Antigravity stop showing up, you are flying blind. Here is the order I follow to diagnose the cause — TS Server restart, ESLint output log, language indicator, tsconfig include, and AI-edited config recovery.
Editor View2026-07-12
The Day My Own DSL Stayed Gray: Adding a Minimal TextMate Grammar to Antigravity
When a custom config file you use every day renders as flat gray text, misreads pile up. This walkthrough builds a minimal TextMate grammar and language-configuration so Antigravity highlights your own file type, with working code and the pitfalls that trip people up.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →