Haliviq
TypeScript

Optional chaining hides typos in property names from the compiler

If the type is loose or any, user?.emial quietly returns undefined instead of raising an error, and the typo ships to production unnoticed. Keep the object properly typed so the compiler can flag the misspelling, and treat a lot of optional chaining as a hint that the data model is not well defined.

What happened

We hit a bug where a user's email did not show on one screen even though the data was complete. The cause was code that read user?.emial, one letter off. There was no error and no warning, and the screen simply rendered an empty value.

This kind of bug ships easily because nothing visibly breaks.

Why it happens

When user is any, the compiler allows access to any property, and the result is any as well. The ?. operator only prevents a throw when the value is null or undefined. It does not check the property name, and at runtime a missing property just evaluates to undefined rather than raising an error.

When the type is defined, for example User | null, writing user?.emial fails with an error saying the property does not exist on type User. So the real problem is not optional chaining but a type that is too loose. Sometimes we also sprinkle ?. everywhere simply because we are not sure what the data looks like.

What we do now

Type data from outside the app properly, either with an interface that matches the response or by validating it with a schema before use. When you do not know the real shape, use unknown instead of any so you are forced to check it first, and keep strict and noImplicitAny turned on.

When you see ?. stacked several levels deep, ask whether that data should really be optional. If not, fix the type, or handle the missing value once at the boundary of the system.

any stays silent, a real type catches the typots
type User = { id: string; email: string; name?: string }

function show(a: any, b: User | null) {
  a?.emial // no error: any allows everything
  b?.emial // error: Property 'emial' does not exist on type 'User'
}

Quick checklist

  1. 1Search for any in code that handles user data and API responses.
  2. 2Replace it with a real type, or with unknown plus validation.
  3. 3Turn on strict and noImplicitAny.
  4. 4Remove ?. where the type says the value is always present.

Rule of thumb

Type your data properly so the compiler can catch typos, and treat heavy optional chaining as a sign to revisit the data model.

We'd love to hear what you're building.

Talk to us