Question
I am testing my UserRouter and loading user data from a JSON file.
data.json
[
{
"id": 1,
"name": "Luke Cage",
"aliases": ["Carl Lucas", "Power Man", "Mr. Bulletproof", "Hero for Hire"],
"occupation": "bartender",
"gender": "male",
"height": {
"ft": 6,
"in": 3
},
"hair": "bald",
"eyes": "brown",
"powers": [
"strength",
"durability",
"healing"
]
}
]
When I build the app, I get this TypeScript error:
ERROR in .../UserRouter.ts
(30,27): error TS7006: Parameter 'user' implicitly has an 'any' type.
UserRouter.ts
import { Router, Request, Response, NextFunction } from 'express';
const Users = require('../data');
export class UserRouter {
router: Router;
constructor() {
// ...
}
/**
* GET one User by id
*/
public getOne(req: Request, res: Response, _next: NextFunction) {
let query = parseInt(req.params.id);
let user = Users.find(user => user.id === query);
if (user) {
res.status(200).send({
message: 'Success',
status: res.status,
user
});
} else {
res.status(404).send({
: ,
: res.
});
}
}
}
userRouter = ().;
userRouter;
Why does TypeScript report that the user parameter implicitly has type any, and how should this code be typed correctly?
Short Answer
By the end of this page, you will understand what the TypeScript error TS7006 means, why it often appears when loading JSON or untyped modules, and how to fix it by defining interfaces and giving arrays explicit types. You will also see how this affects callback parameters like the user inside .find().
Concept
TypeScript tries to understand the type of every variable, function parameter, and return value. The error TS7006: Parameter 'xxx' implicitly has an 'any' type appears when TypeScript cannot figure out a parameter's type and your project does not allow silent any values.
In your example, the important part is this line:
let user = Users.find(user => user.id === query);
The callback parameter user gets its type from the type of Users. If Users is properly typed as something like User[], then TypeScript knows that user is a User. But if Users comes from require('../data') without a clear type, TypeScript may treat it as any, or fail to infer the callback parameter type safely.
This matters because TypeScript's main benefit is catching mistakes before runtime. If everything becomes any, TypeScript cannot help you detect problems like:
- misspelled property names
Mental Model
Think of TypeScript like a warehouse labeling system.
- A
Userinterface is the label describing what each box contains. - A
User[]is a shelf full of those labeled boxes. .find(user => ...)means: "look through each box on the shelf."
If the shelf has no label, TypeScript does not know what kind of boxes are on it. Then when you say user.id, it cannot safely tell what user is supposed to be.
So the problem is usually not the worker checking each box (user => ...). The problem is that the shelf (Users) was never labeled clearly.
Syntax and Examples
The core idea is to define your data shape and use it everywhere.
Define an interface
interface Height {
ft: number;
in: number;
}
interface User {
id: number;
name: string;
aliases: string[];
occupation: string;
gender: string;
height: Height;
hair: string;
eyes: string;
powers: string[];
}
Type an array of users
const users: User[] = [
{
id: 1,
name: 'Luke Cage',
aliases: ['Carl Lucas', 'Power Man'],
occupation: 'bartender',
gender: ,
: { : , : },
: ,
: ,
: [, , ]
}
];
Step by Step Execution
Consider this small example:
interface User {
id: number;
name: string;
}
const users: User[] = [
{ id: 1, name: 'Luke Cage' },
{ id: 2, name: 'Jessica Jones' }
];
const query = 2;
const foundUser = users.find(user => user.id === query);
Here is what happens step by step:
-
TypeScript reads the
Userinterface.- A
Usermust haveidandname.
- A
-
TypeScript reads
const users: User[].- This means
usersis an array ofUserobjects.
- This means
Real World Use Cases
This concept appears often in real projects whenever data comes from outside your code.
Common situations
-
Reading JSON files
- seed data
- test fixtures
- local configuration
-
API responses
- user lists from a backend
- product data from a service
- analytics records
-
Database query results
- rows returned by an ORM or query builder
-
Express route handlers
- searching, filtering, and validating records before sending a response
Example: filtering API data
interface Product {
id: number;
name: string;
price: number;
}
const products: Product[] = getProductsSomehow();
const expensive = products.filter(product => product.price > 100);
The callback parameter product is correctly inferred only because is typed.
Real Codebase Usage
In real codebases, developers usually solve this by typing data close to where it enters the system.
Common patterns
1. Define interfaces or types for domain models
export interface User {
id: number;
name: string;
aliases: string[];
occupation: string;
gender: string;
height: {
ft: number;
in: number;
};
hair: string;
eyes: string;
powers: string[];
}
This creates a reusable contract for the rest of the app.
2. Type imported data immediately
import rawUsers from '../data.json';
import { User } from './types';
const users: User[] = rawUsers;
This is better than letting untyped data spread through the application.
Common Mistakes
1. Typing only the callback parameter instead of the source data
This works:
Users.find((user: User) => user.id === query);
But if Users itself is untyped, you still have a weakly typed source. A better approach is:
const users: User[] = rawUsers;
users.find(user => user.id === query);
2. Using require() without clear types
Broken or weakly typed example:
const Users = require('../data');
const user = Users.find(user => user.id === 1);
Better:
rawUsers ;
: [] = rawUsers;
Comparisons
| Approach | Example | Pros | Cons |
|---|---|---|---|
Untyped require | const Users = require('../data') | Quick to write | Weak inference, more any, less safety |
| Typed import + interface | import rawUsers from '../data.json'; const users: User[] = rawUsers; | Best type safety, clear data shape | Requires interface definition |
| Type callback parameter only | users.find((user: User) => ...) | Fixes the immediate callback error | Does not fully type the source data |
Use any | const Users: any = ... | Removes compiler complaints fast |
Cheat Sheet
TS7006 quick fix checklist
TS7006means TypeScript cannot determine a parameter type safely.- Callback parameters often get their type from the array or function they belong to.
- If
.find(user => ...)fails, check the type of the array first. - Define an interface for your data shape.
- Type imported JSON as
YourType[]. - Remember:
.find()returnsT | undefined.
Useful syntax
interface User {
id: number;
name: string;
}
const users: User[] = rawUsers;
const user = users.find(user => user.id === query);
const user = users.find((: ) => user. === query);
FAQ
Why does TypeScript say a parameter implicitly has any type?
Because TypeScript cannot infer the parameter type, and your settings disallow unnamed any values.
Why is the .find() callback parameter not inferred correctly?
Because the array being searched is not clearly typed, so TypeScript has no reliable item type to use for the callback parameter.
Should I type the callback parameter manually?
You can, but it is usually better to type the array or imported data source so inference works everywhere.
How do I type JSON data in TypeScript?
Create an interface for the JSON shape, import the JSON, and assign it to a variable typed as that interface or array of interfaces.
What type does .find() return in TypeScript?
It returns the matching item type or undefined if no match is found.
Is using any okay to fix TS7006?
It removes the error, but it also removes type safety. It is usually a poor long-term solution.
Is require() worse than import in TypeScript?
Not always, but import usually works more smoothly with TypeScript's type inference and module typing.
How should I type my Express route data?
Mini Project
Description
Build a small Express-style user lookup module that loads typed user data and returns one user by ID. This project demonstrates how proper typing fixes TS7006, improves autocomplete, and makes .find() callbacks safe and predictable.
Goal
Create a typed user lookup flow where JSON-like data is modeled with interfaces and searched safely by ID.
Requirements
- Define TypeScript interfaces for the user data structure.
- Store a small array of users using the typed interface.
- Write a function that accepts an ID and returns the matching user.
- Handle the case where the ID is invalid or no user is found.
- Use
.find()without triggeringTS7006.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular @ViewChild Returning Undefined: Lifecycle, Child Components, and Fixes
Learn why Angular @ViewChild can be undefined, when it becomes available, and how to access child components correctly using lifecycle hooks.