---
name: no-any-types
description: Use when writing TypeScript and tempted to type something as `any`, or when reviewing code that contains `any`. This skill applies whenever you encounter untyped data, generic utility functions, GraphQL resolvers, API responses, or JSON parsing — any situation where `any` might seem like the easy option. Always check this skill before using `any`.
---

# No Any Types

## Overview

Never use `any` in TypeScript. It disables type checking entirely — defeating the purpose of TypeScript. There is always a better alternative.

## Why `any` Is Harmful

- Removes compile-time error checking
- Kills IDE autocomplete and intellisense
- Allows type errors to silently reach runtime
- Spreads: `any` infects everything it touches

## Decision Tree

```
Is the data truly unknown at compile time?
  → Yes: use `unknown` with a type guard
  → No: does the function work for multiple types?
      → Yes: use generics `<T>`
      → No: does the value have a fixed set of types?
          → Yes: use union types `string | number`
          → No: create an interface
```

## The Replacements

### Use existing types or create an interface
```typescript
// ❌
function process(data: any) { return data.id; }

// ✅
function process(data: User) { return data.id; }
```

### Use generics for reusable functions
```typescript
// ❌
function identity(x: any): any { return x; }

// ✅
function identity<T>(x: T): T { return x; }
```

### Use union types for known variants
```typescript
// ❌
function format(value: any): string { ... }

// ✅
function format(value: string | number | boolean): string { ... }
```

### Use `unknown` for external/runtime data
```typescript
// ❌
function parseJson(json: string): any { return JSON.parse(json); }

// ✅
function parseJson(json: string): unknown { return JSON.parse(json); }
// Then narrow with a type guard before use
```

## Special Case: GraphQL Resolvers

In GraphQL resolvers, omit parameter types entirely — they're inferred from generated schema types:

```typescript
// ❌ Explicit any
async function resolver(parent: any, args: any, context: any) { ... }

// ✅ Let codegen infer
async function resolver(parent, args, context) { ... }
```

## When You Think You Need `any`

1. Check if the type already exists in the codebase
2. Check `@types/*` packages for the library
3. Define the missing interface yourself
4. Use `unknown` + type guard for truly dynamic data
5. Use generics for reusable patterns

If none of those work, use `unknown` — it forces you to narrow before use, making the unsafe operation visible.

## Enforcement

`@typescript-eslint/no-explicit-any` must be enabled. When you encounter `any` in existing code during a review, flag it and suggest the appropriate replacement from the decision tree above.
