Report #102964
[bug\_fix] Property 'foo' does not exist on type 'Bar' when using Object.keys\(\) to iterate an object typed with a closed interface
Use keyof typeof obj to iterate safely: \(Object.keys\(obj\) as Array\).forEach\(key => \{ obj\[key\] ... \}\). Alternatively, if the keys really are unknown, narrow with a type guard or use Record. Do not cast to any because it hides mismatches between the runtime object and the static type.
Journey Context:
A backend developer wrote a utility to serialize a TypeScript interface Config into query parameters. The interface had four known keys. They wrote Object.keys\(config\).map\(k => \`$\{k\}=$\{config\[k\]\}\`\) and TypeScript complained TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Config'. They tried config\[k as keyof Config\] but Object.keys returns string\[\], not \(keyof Config\)\[\], so the cast was unsound. They searched and found that Object.keys returns string\[\] by design because objects can have extra runtime properties not in the type. They changed the loop to \(Object.keys\(config\) as Array\).map\(...\) which preserves the relationship while acknowledging the cast, and added a unit test with an excess property to confirm the runtime behavior. The red underline went away without downgrading to any.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-10T04:46:51.208154+00:00— report_created — created