Question

How to Fix TS7006: Parameter Implicitly Has an 'any' Type in TypeScript

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({
        message: 'No User found with the given id.',
        status: res.status
      });
    }
  }
}

const userRouter = new UserRouter().router;
export default 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
  • wrong data shapes
  • invalid comparisons
  • missing nested fields

The real fix is usually not to manually type the callback parameter first. The better fix is to type the data source correctly so TypeScript can infer the callback parameter automatically.

For this data, a proper solution is to define a User interface and make sure Users is typed as User[].

Mental Model

Think of TypeScript like a warehouse labeling system.

  • A User interface 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.

Take Quiz

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: 'male',
    height: { ft: 6, in: 3 },
    hair: 'bald',
    eyes: 'brown',
    powers: ['strength', 'durability', 'healing']
  }
];

Now .find() works with inference:

const result = users.find(user => user.id === 1);

Here, TypeScript knows:

  • users is User[]
  • each user inside .find() is a User
  • result is User | undefined

Applying it to imported JSON

A common pattern is:

import rawUsers from '../data.json';

const users: User[] = rawUsers;

Then use:

const user = users.find(user => user.id === query);

You can also type the callback parameter directly

const user = users.find((user: User) => user.id === query);

This works, but it is usually better to type users correctly and let TypeScript infer the callback parameter automatically.

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:

  1. TypeScript reads the User interface.

    • A User must have id and name.
  2. TypeScript reads const users: User[].

    • This means users is an array of User objects.
  3. TypeScript reads .find(user => user.id === query).

    • Because users is User[], each item in the array is a User.
    • So the callback parameter user is automatically inferred as User.
  4. TypeScript checks user.id.

    • This is valid because id exists on User.
  5. TypeScript computes the result type.

    • .find() may return a matching User.
    • If nothing matches, it returns undefined.
    • So foundUser has type User | undefined.

If users had no type, then TypeScript might not know what user is, which leads to weaker checking or errors like TS7006.

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 products is typed.

Example: validating configuration

interface FeatureFlag {
  key: string;
  enabled: boolean;
}

const flags: FeatureFlag[] = loadFlags();
const betaFlag = flags.find(flag => flag.key === 'beta-dashboard');

Again, the callback parameter type depends on the array type.

Take Quiz

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.

3. Use guard clauses for missing results

const user = users.find(user => user.id === query);

if (!user) {
  return res.status(404).send({ message: 'No User found with the given id.' });
}

return res.status(200).send({ message: 'Success', user });

This is a common Express pattern because .find() returns undefined when nothing matches.

4. Validate route parameters

const query = Number(req.params.id);

if (Number.isNaN(query)) {
  return res.status(400).send({ message: 'Invalid id.' });
}

This prevents bad input from reaching the search logic.

5. Prefer typed imports over require where possible

Using import usually works better with TypeScript's type system than using untyped require(...).

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:

import rawUsers from '../data.json';
const users: User[] = rawUsers;

3. Forgetting that .find() can return undefined

Broken example:

const user = users.find(user => user.id === query);
console.log(user.name);

If no user is found, this will fail.

Better:

const user = users.find(user => user.id === query);
if (user) {
  console.log(user.name);
}

4. Using parseInt() carelessly

This is valid, but can be improved:

const query = parseInt(req.params.id);

Better:

const query = Number(req.params.id);
if (Number.isNaN(query)) {
  return res.status(400).send({ message: 'Invalid id.' });
}

5. Assuming JSON automatically gives perfect TypeScript types

JSON is just data. TypeScript needs a type definition to understand its shape safely.

6. Confusing any with a real fix

You could silence the error like this:

const Users: any = require('../data');

But this turns off type safety. It hides the problem instead of solving it.

Comparisons

ApproachExampleProsCons
Untyped requireconst Users = require('../data')Quick to writeWeak inference, more any, less safety
Typed import + interfaceimport rawUsers from '../data.json'; const users: User[] = rawUsers;Best type safety, clear data shapeRequires interface definition
Type callback parameter onlyusers.find((user: User) => ...)Fixes the immediate callback errorDoes not fully type the source data
Use anyconst Users: any = ...Removes compiler complaints fastLoses most TypeScript benefits

any vs typed data

OptionMeaning
anyTypeScript stops checking that value properly
UserOne object with the expected user fields
User[]An array of user objects
`Userundefined`
Take Quiz

Cheat Sheet

TS7006 quick fix checklist

  • TS7006 means 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() returns T | 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: User) => user.id === query);

Safer Express example

const query = Number(req.params.id);
if (Number.isNaN(query)) {
  return res.status(400).send({ message: 'Invalid id.' });
}

const user = users.find(user => user.id === query);
if (!user) {
  return res.status(404).send({ message: 'No User found with the given id.' });
}

return res.status(200).send({ message: 'Success', user });

Rule of thumb

If a callback parameter becomes any, type the input data source first.

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?

Define a domain type such as User, type the source data as User[], validate request input, and handle the case where no item is found.

Take Quiz

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 triggering TS7006.
Take Quiz

Keep learning

Related questions

View more