---
description: Learn why TypeScript throws TS7053 (“Element implicitly has an
  'any' type”) and how to fix it using keyof, type guards, or index signatures.
keywords:
  - typescript
  - ts7053
  - keyof
  - type guard
  - index signature
  - noImplicitAny
publishDate: 2025-07-22
shortTitle: No Implicit Any Type String Index Error
tags:
  - TypeScript
title: "TypeScript TS7053: “Element implicitly has an 'any' type” (Fix)"
---

## TL;DR

TS7053 shows up when you index an object with a `string` key that TypeScript cannot prove is valid.

Fix it by doing one of these:

- If you control the key, accept `keyof typeof item`.
- If the key is dynamic, narrow it with a type guard or runtime check.
- Avoid permissive index signatures unless the object is intentionally open-ended.

## The problem

Here is the error:

```log
Error ts(7053) ― Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; type: string; }'. No index signature with a parameter of type 'string' was found on type '{ name: string; type: string; }'.
```

You usually see it with `noImplicitAny` enabled, often through `strict` in `tsconfig.json`.

The core issue is simple.

This compiles in JavaScript:

```ts
item[key];
```

But TypeScript has to answer a question first.

Is `key` actually one of the keys on `item`?

If `key: string`, the answer is "could be anything".

So TypeScript blocks it.

```ts twoslash
// @errors: 7053
const item = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: string) {
  console.log(item[key]);
}
```

`item` has two keys: `name` and `type`.

`key` could be `"lol"`, `"price"`, or `"__proto__"`.

TypeScript does not let you pretend those are safe.

## Solutions

Pick the fix based on where the key comes from.

### 1. You know the key set, so restrict it with `keyof`

This is the cleanest fix when callers should only use real keys.

```ts twoslash
const item = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: keyof typeof item) {
  console.log(item[key]);
}
```

If someone tries `logValue("price")`, TypeScript stops them.

This is what you want when you control the input.

### 2. You do not control the key, so check at runtime

If the key comes from user input, query params, API data, or config, then it is `string`.

At that point you need a runtime check.

```ts twoslash
const item = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: string) {
  if (key in item) {
    console.log(item[key as keyof typeof item]);
  }
}
```

This keeps runtime behavior honest.

The remaining assertion exists because `key in item` narrows at runtime, but TypeScript still sees `key` as `string` without a stronger predicate.

If you want the narrowing to be fully typed, use a type guard.

### 3. Make the runtime check a type guard

This gives you both runtime safety and clean types inside the branch.

```ts twoslash
const item = {
  name: "Apple",
  type: "fruit",
};

type KeyOfItem = keyof typeof item;

function isKeyOfItem(key: string): key is KeyOfItem {
  return key in item;
}

function logValue(key: string) {
  if (isKeyOfItem(key)) {
    console.log(item[key]);
    //                 ^?
  }
}
```

This is my default when keys are dynamic.

It reads well and it scales.

### 4. You want a quick escape hatch, so assert

This silences the error, but it does not validate anything.

```ts twoslash
const item = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: string) {
  console.log(item[key as keyof typeof item]);
}
```

If `key` is not real, you get `undefined`.

Use this only when you have a guarantee TypeScript cannot see.

### 5. The object is intentionally open-ended, so add an index signature

If the object genuinely allows arbitrary string keys, model it that way.

```ts twoslash
const item: { [key: string]: string } = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: string) {
  const value = item[key];
  //    ^?

  console.log(value);
}
```

This trades precision for flexibility.

Be careful. You just told TypeScript that every property is a `string`, even ones that do not exist.

If you enable `noUncheckedIndexedAccess`, TypeScript will force you to handle missing keys.

```json title=tsconfig.json
{
  "compilerOptions": {
    "noUncheckedIndexedAccess": true
  }
}
```

Then this becomes `string | undefined` instead of pretending it is always there.

```ts twoslash
// @noUncheckedIndexedAccess
const item: { [key: string]: string } = {
  name: "Apple",
  type: "fruit",
};

function logValue(key: string) {
  const value = item[key];
  //    ^?

  console.log(value);
}
```

### 6. Do not do this unless you mean it

A permissive index signature defeats the point.

```ts twoslash
interface Item {
  [key: string]: any;
  name: string;
  quantity: number;
}

const item: Item = {
  name: "Apple",
  quantity: 6,
};

function logValue(key: string) {
  const value = item[key];
  //    ^?

  console.log(value);
}
```

This says "any string key is fine", and then TypeScript can no longer protect you.

If you reach for this, pause.

You are probably hiding a modeling problem.

## Wrapping up

TS7053 is TypeScript forcing you to be honest about dynamic keys.

- Use `keyof` when the key set is known.
- Use `in` checks or type guards when the key is dynamic.
- Use index signatures only when the object is truly open-ended.
- Treat type assertions as a last resort.

Once you pick the right shape, the error goes away and your code stays predictable.