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:
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:
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.
const const item: { name: string; type: string;}
item = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: string): void
logValue(key: string
key: string) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const item: { name: string; type: string;}
item[key: string
key]);Error ts(7053) ― }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.
const const item: { name: string; type: string;}
item = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: keyof typeof item): void
logValue(key: "name" | "type"
key: keyof typeof const item: { name: string; type: string;}
item) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const item: { name: string; type: string;}
item[key: "name" | "type"
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.
const const item: { name: string; type: string;}
item = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: string): void
logValue(key: string
key: string) { if (key: string
key in const item: { name: string; type: string;}
item) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const item: { name: string; type: string;}
item[key: string
key as keyof typeof const item: { name: string; type: string;}
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.
const const item: { name: string; type: string;}
item = { name: string
name: "Apple", type: string
type: "fruit",};
type type KeyOfItem = "name" | "type"
KeyOfItem = keyof typeof const item: { name: string; type: string;}
item;
function function isKeyOfItem(key: string): key is KeyOfItem
isKeyOfItem(key: string
key: string): key: string
key is type KeyOfItem = "name" | "type"
KeyOfItem { return key: string
key in const item: { name: string; type: string;}
item;}
function function logValue(key: string): void
logValue(key: string
key: string) { if (function isKeyOfItem(key: string): key is KeyOfItem
isKeyOfItem(key: string
key)) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const item: { name: string; type: string;}
item[key]);key: "name" | "type"
}}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.
const const item: { name: string; type: string;}
item = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: string): void
logValue(key: string
key: string) { var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const item: { name: string; type: string;}
item[key: string
key as keyof typeof const item: { name: string; type: string;}
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.
const const item: { [key: string]: string;}
item: { [key: string
key: string]: string } = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: string): void
logValue(key: string
key: string) { const value = const item: { [key: string]: string;}
item[key: string
key];const value: string
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const value: string
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.
{ "compilerOptions": { "noUncheckedIndexedAccess": true }}Then this becomes string | undefined instead of pretending it is always there.
const const item: { [key: string]: string;}
item: { [key: string
key: string]: string } = { name: string
name: "Apple", type: string
type: "fruit",};
function function logValue(key: string): void
logValue(key: string
key: string) { const value = const item: { [key: string]: string;}
item[key: string
key];const value: string | undefined
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const value: string | undefined
value);}6. Do not do this unless you mean it
A permissive index signature defeats the point.
interface interface Item
Item { [key: string
key: string]: any; Item.name: string
name: string; Item.quantity: number
quantity: number;}
const const item: Item
item: interface Item
Item = { Item.name: string
name: "Apple", Item.quantity: number
quantity: 6,};
function function logValue(key: string): void
logValue(key: string
key: string) { const value = const item: Item
item[key: string
key];const value: any
var console: Console
console.Console.log(...data: any[]): void
The console.log() static method outputs a message to the console.
log(const value: any
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
keyofwhen the key set is known. - Use
inchecks 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.