# Ban the 'any' Type
## Rule
The `any` type MUST NOT be used in production TypeScript code. Use `unknown` for truly unknown types, generics for type-safe flexibility, and union types for known alternatives.
## Alternatives to 'any'
| Instead of | Use | When |
|-----------|-----|------|
| `any` | `unknown` | Truly unknown type (API response) |
| `any` | Generic `T` | Flexible but type-safe function |
| `any` | Union type | Known set of possible types |
| `any` | `Record<string, unknown>` | Unknown object shape |
| `any[]` | `unknown[]` | Unknown array contents |
## Good Examples
```typescript
// unknown + type narrowing
function processInput(input: unknown): string {
if (typeof input === "string") {
return input.toUpperCase();
}
if (typeof input === "number") {
return input.toString();
}
throw new Error(`Unexpected input type: ${typeof input}`);
}
// Generics for type-safe flexibility
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
// Typed API response
interface ApiResponse<T> {
data: T;
error: string | null;
status: number;
}
async function fetchUser(id: string): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
return response.json() as Promise<ApiResponse<User>>;
}
// Record with unknown values
function logMetadata(meta: Record<string, unknown>): void {
for (const [key, value] of Object.entries(meta)) {
console.log(`${key}: ${String(value)}`);
}
}
```
## Bad Examples
```typescript
// BAD: any everywhere
function process(data: any): any {
return data.map((item: any) => item.value);
}
// BAD: any as escape hatch
const result = someLibraryFunction() as any;
result.doSomething(); // No type checking at all
// BAD: any in generics
function wrapper<T = any>(value: T): T {
return value;
}
```
## Enforcement
- ESLint: @typescript-eslint/no-explicit-any (error)
- ESLint: @typescript-eslint/no-unsafe-assignment (error)
- ESLint: @typescript-eslint/no-unsafe-member-access (error)
- tsconfig: "noImplicitAny": true (included in strict)