ProgrammingFrontend Developer

How does the mechanism for accessing optional properties work in TypeScript, what problems can arise, and how to avoid them?

Pass interviews with Hintsage AI assistant

Answer.

Optional properties in TypeScript are denoted by a question mark (?) after the property name. This means that the property can either be set or omitted from the object. This is convenient for describing structures where not all fields are required.

Example:

interface User { id: number; name?: string; } const u1: User = { id: 1 }; // OK const u2: User = { id: 2, name: 'Ivan' }; // OK

Nuances:

  • An optional property can be not only undefined, but also completely absent from the object.
  • Checking for value presence (e.g., if (user.name)) does not distinguish undefined from absence.
  • A common bug is not considering that the property may be undefined and accessing methods/properties without checks.

To safeguard:

  • Use checks for undefined:
if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
  • You can use the optional chaining operator:
console.log(user.name?.toUpperCase());

Trick question.

If an object defines an interface { foo?: string }, can the property foo always be only a string or undefined? Can we assign null to it, for example?

Incorrect answer:

  • "An optional property can only be a string or undefined, nothing else."

Correct answer:

  • In fact, if you explicitly assign null, TypeScript allows this, but only if the type is extended to string | null. By default, it’s only string or undefined.
  • Example:
interface A { foo?: string } let x: A = { foo: null }; // Error!

Examples of real errors due to ignorance of the nuances of the topic.


Story

In a large project, some objects came from the server without certain optional fields. A programmer directly called methods on these properties (e.g., toLowerCase()), which led to runtime errors if the field was absent. To solve the problem, the team implemented strict checks and linter rules for accessing optional fields.


Story

In logical expressions, they confused the presence of the property and its truthiness: if (user.email) did not trigger for empty strings, although the property was set. A bug arose, causing some notifications not to be sent to users.


Story

The team decided to assign the value null to an optional property, thinking this was correct. TypeScript raised an error, and to work around it, they had to expand the type to string | null, which required a review of the entire business logic related to these objects.