TypeScript throws TS7053 when you access an object property using a variable key and the compiler cannot prove that the key exists on the object. The full message looks like this:
Element implicitly has an 'any' type because expression of type 'string'
can't be used to index type '{ foo: string; bar: number }'.
No index signature with a parameter of type 'string' was found on type
'{ foo: string; bar: number }'. ts(7053)You get this error when noImplicitAny is on (which is on by default in strict mode) and the compiler cannot resolve your bracket-notation access to a known property. Here is what is happening and five ways to fix it.
The simplest example that reproduces TS7053
const user = { name: "Ana", age: 27, city: "Manila" };
function getField(key: string) {
return user[key]; // TS7053
}The parameter key is typed as string, but TypeScript can only guarantee the object has three specific keys. A random string could be anything, so the compiler blocks the access.
Fix 1: Narrow the key type with keyof
This is the correct fix in most cases. Tell TypeScript that the key must be one of the object’s actual keys:
const user = { name: "Ana", age: 27, city: "Manila" };
function getField(key: keyof typeof user) {
return user[key]; // OK
}
getField("name"); // OK
getField("email"); // Error caught at compile timeNow the callers get autocomplete for valid keys and typos are caught before runtime.
Fix 2: Add an index signature to the type
Use this when the object is a lookup table and any string key is legitimate:
type Translations = { [key: string]: string };
const tr: Translations = {
hello: "kumusta",
goodbye: "paalam",
};
function translate(word: string): string | undefined {
return tr[word]; // OK
}The tradeoff is that TypeScript will now let you read tr["anything"] without complaint, so you lose autocomplete. Only use this pattern when the object is genuinely open-ended.
Fix 3: Use Record with a union key type
When you want a lookup with a fixed set of allowed keys, Record is cleaner than an index signature:
type Status = "draft" | "published" | "archived";
const statusColor: Record<Status, string> = {
draft: "#999",
published: "#2D6A4F",
archived: "#666",
};
function getColor(status: Status): string {
return statusColor[status]; // OK
}This gives you full autocomplete for the four statuses, and the compiler forces you to handle every key when you construct statusColor.
Fix 4: Type guard with the in operator
When your key really is an untrusted string (from an API response, URL params, form input), use a type guard before the access:
const user = { name: "Ana", age: 27, city: "Manila" };
function getField(key: string) {
if (key in user) {
return user[key as keyof typeof user]; // OK
}
return undefined;
}The in check narrows the string to a known key at runtime, and the cast becomes safe because you have already verified it.
Fix 5: The escape hatch (use sparingly)
If you are prototyping or migrating from JavaScript and want to move past the error quickly:
function getField(key: string) {
return (user as Record<string, unknown>)[key];
}This bypasses the check by asserting the object as a permissive record. It works, but it throws away the type safety that TypeScript is trying to give you. Only use this when the surrounding code is temporary.
Common places TS7053 shows up in real projects
- React form handlers. You have a form state object and want a single change handler:
setState({ ...state, [name]: value }). Typenameaskeyof typeof stateor add an index signature. - API response mapping. You loop over an unknown response and index by string. Fix it by defining the response type and using
keyof, or by using a type guard. - Configuration lookups. A settings object with environment-specific keys. Use
Record<EnvironmentName, Config>. - Icon or color maps. A dictionary of icon names to components. Use
Recordwith a string-literal union. - Migrating .js to .ts. Legacy JavaScript often relies on dynamic property access. Fix these one by one with keyof or add gradual index signatures.
Which fix should you pick?
Rule of thumb:
- Key comes from a known set at compile time: Fix 1 (keyof) or Fix 3 (Record with union).
- Object is a genuine dictionary and any string is valid: Fix 2 (index signature).
- Key comes from user input, API, or URL: Fix 4 (in operator guard).
- You are prototyping and will fix it later: Fix 5 (Record cast).
Fix 1 and Fix 3 are what you want most of the time in production TypeScript. They give you real autocomplete and catch typos before deployment.
Verifying your fix
Run the TypeScript compiler in noEmit mode to check without producing output files:
npx tsc --noEmit
If TS7053 no longer appears in the output, your fix is in place. If you use VS Code, the error should also disappear from the Problems panel within a few seconds of saving the file.
Official documentation
Frequently asked questions
What triggers TS7053 in TypeScript?
TS7053 fires when you use bracket notation to access a property using a variable of type string or number, and the object type has no index signature or matching key. TypeScript cannot narrow the access to a known type, so it refuses rather than silently returning any.
Why not just disable noImplicitAny?
You can, but you give up one of TypeScript’s most useful checks. Every dynamic property access becomes any, which hides real bugs. Fix the individual access with keyof or an index signature instead, and keep noImplicitAny on for the rest of your code.
What is the difference between keyof and Record?
keyof extracts the keys from an existing type as a union. Record constructs a new object type from a key type and a value type. Use keyof when the object already exists and you want to type its keys. Use Record when you are defining a new lookup type from scratch.
Does the “in” operator narrow the key type automatically?
Partially. The in operator narrows the object side of the check, not the string side. That is why you still need “key as keyof typeof user” inside the if block. TypeScript is planning better narrowing here in future versions but as of 5.x you need the assertion.
Can I fix TS7053 in a .d.ts file?
Yes. If the error is coming from a third-party library that lacks proper types, add an index signature to its declared type in a local .d.ts file. Use module augmentation so your fix does not conflict with the library’s shipped types.
Does TS7053 appear at runtime or compile time?
Compile time only. TS7053 is a static type check that runs when tsc processes your source. Your compiled JavaScript will still execute the bracket access at runtime, it just may return undefined instead of the value you expected if the key is not present.
