Fix TypeScript Error: Element implicitly has an 'any' type (ts7053) when using dynamic keys

intermediate🔵 TypeScript2026-04-06| TypeScript 3.0+, VS Code, Node.js, React, or any modern TS environment.

Error Message

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type. ts(7053)
#typescript#frontend#web-development#coding-tips

The ProblemYou’re coding along, trying to pull a value from an object using a variable key, and suddenly VS Code hits you with a red underline. This usually happens when you're looping through an object or using a string from an API to access a specific property.

interface User {
  name: string;
  age: number;
}

const userData: User = {
  name: "John",
  age: 30
};

const key = "name";

// ❌ Error: Element implicitly has an 'any' type because expression of type 'string' 
// can't be used to index type 'User'.
console.log(userData[key]);

Why this happensThe TypeScript compiler is protective. When you define the User interface, you've told the system that only name and age exist.

The trouble starts because key is inferred as a generic string. To TypeScript, a string could be anything—like "password" or "random_field"—that doesn't actually exist on your object. If the compiler can't guarantee that userData[key] will return a valid value, it defaults the type to any. Under strict noImplicitAny rules, this triggers the ts(7053) error to prevent potential runtime crashes.

How to fix it### Method 1: Type Assertion with 'keyof'Use a type assertion if you are 100% sure the variable is a valid property. This is the fastest way to bypass the error when working with static interfaces.

// Solution: Tell TS exactly what this string represents
console.log(userData[key as keyof User]);

// Pro-tip: Use 'typeof' if you don't want to import the Interface
console.log(userData[key as keyof typeof userData]);

Method 2: Use an Index SignatureSometimes objects are dynamic by design, like a collection of form inputs. You can update your interface to allow flexible string keys. This tells the compiler: "This object can have any string key, provided the value is either a string or a number."

interface User {
  name: string;
  age: number;
  [key: string]: string | number; // The index signature
}

const userData: User = {
  name: "John",
  age: 30,
  location: "London" // No longer causes an error
};

Method 3: The Record Utility TypeThe Record<K, T> helper is a cleaner alternative for simple mappings. It’s perfect for things like configuration objects, CSS styles, or status codes where keys share a common value type.

// Example: Mapping HTTP status codes to messages
const statusMessages: Record<number, string> = {
  200: "Success",
  404: "Not Found",
  500: "Server Error"
};

const code = 404;
console.log(statusMessages[code]); // Works perfectly

Method 4: Fixing Object.keys() LoopsBy default, Object.keys() returns an array of generic strings (string[]). This is a common source of frustration during loops. You must explicitly cast the key during the iteration.

Object.keys(userData).forEach((key) => {
  // ✅ Cast the key to the specific keys of your object
  const value = userData[key as keyof User];
  console.log(`${key}: ${value}`);
});

VerificationHow do you know it's fixed? First, ensure the red squiggle in your editor has vanished. Next, hover over the variable where you access the object. It should show a specific type, like string or number, rather than any. Finally, run npm run build or tsc. If the compiler finishes without 0 errors, your type safety is intact.

Prevention- Avoid using the generic string type for variables that act as keys; use keyof MyInterface instead.- Sanitize external data from APIs by mapping it to a Record type immediately.- Keep strict: true in your tsconfig.json. It might feel annoying now, but it prevents 90% of "undefined is not a function" errors in production.

Related Error Notes