What is TS7006?
TS7006 occurs when TypeScript cannot infer the type of a function parameter and the noImplicitAny compiler option is enabled. This forces you to explicitly declare types, preventing accidental use of any.
// Example of TS7006 error function greet(name) { // Error: Parameter 'name' implicitly has an 'any' type console.log(`Hello, ${name}!`); }
Why Does This Error Exist?
The noImplicitAny option (enabled by default with strict: true) ensures type safety by requiring explicit type annotations. Without this, TypeScript would silently treat untyped parameters as any, defeating the purpose of type checking.
Common Causes
1. Untyped Function Parameters
// โ No type annotation function add(a, b) { // Error on both 'a' and 'b' return a + b; } // โ Add type annotations function add(a: number, b: number): number { return a + b; }
2. Arrow Functions
// โ Untyped arrow function const double = (n) => n * 2; // Error! // โ Add type annotation const double = (n: number): number => n * 2;
3. Callback Functions
// โ Callback without types [1, 2, 3].forEach((item) => { // Usually OK due to inference console.log(item); }); // โ But standalone callbacks need types const callback = (item) => { // Error! console.log(item); };
4. Event Handlers
// โ Event handler without type function handleClick(event) { // Error! console.log(event.target); } // โ Add proper event type function handleClick(event: MouseEvent) { console.log(event.target); }
Solutions
1. Add Type Annotations
// Basic types function greet(name: string): void { console.log(`Hello, ${name}!`); } // Object types function processUser(user: { name: string; age: number }) { console.log(user.name, user.age); } // Array types function sumNumbers(numbers: number[]): number { return numbers.reduce((a, b) => a + b, 0); }
2. Use Interfaces or Type Aliases
interface User { name: string; email: string; } function sendEmail(user: User, message: string): void { // Implementation } // Or with type alias type Callback = (value: string) => void; function processAsync(callback: Callback): void { callback('result'); }
3. Use Generics
// โ Generic function function identity<T>(value: T): T { return value; } // โ Generic arrow function const toArray = <T>(value: T): T[] => [value];
4. Explicit 'any' (Last Resort)
// โ If you truly need any, be explicit function logAnything(value: any): void { console.log(value); } // Better: use 'unknown' for safer any-like behavior function processUnknown(value: unknown): void { if (typeof value === 'string') { console.log(value.toUpperCase()); } }
๐ก Pro Tip
Prefer unknown over any when you don't know the type. It provides type safety by requiring type checks before use.
Real-World Examples
React Event Handlers
// โ Untyped event const handleChange = (e) => { // Error! console.log(e.target.value); }; // โ Properly typed const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { console.log(e.target.value); }; // โ Alternative with inline annotation <input onChange={(e: React.ChangeEvent<HTMLInputElement>) => { console.log(e.target.value); }} />
Express.js Route Handlers
import { Request, Response } from 'express'; // โ Untyped app.get('/users', (req, res) => { // Error! res.json({ users: [] }); }); // โ Properly typed app.get('/users', (req: Request, res: Response) => { res.json({ users: [] }); });
Utility Functions
// โ Untyped utility const debounce = (fn, delay) => { // Error! let timeoutId; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn(...args), delay); }; }; // โ Properly typed const debounce = <T extends (...args: any[]) => any>( fn: T, delay: number ): ((...args: Parameters<T>) => void) => { let timeoutId: ReturnType<typeof setTimeout>; return (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn(...args), delay); }; };
โ ๏ธ Don't Disable noImplicitAny
While you can disable this check in tsconfig.json, it's strongly recommended to keep it enabled. It catches many potential bugs at compile time.
Summary
- TS7006 requires explicit type annotations for parameters
- Always type function parameters for better code quality
- Use interfaces and type aliases for complex types
- Prefer
unknownoveranywhen type is truly unknown - Keep
noImplicitAnyenabled for maximum type safety