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:
undefined, but also completely absent from the object.if (user.name)) does not distinguish undefined from absence.undefined and accessing methods/properties without checks.To safeguard:
undefined:if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
console.log(user.name?.toUpperCase());
If an object defines an interface
{ foo?: string }, can the propertyfooalways be only a string orundefined? Can we assignnullto it, for example?
Incorrect answer:
undefined, nothing else."Correct answer:
null, TypeScript allows this, but only if the type is extended to string | null. By default, it’s only string or undefined.interface A { foo?: string } let x: A = { foo: null }; // Error!
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.