DEV Community

Cover image for An Optional Property Isn't the Same as undefined
Byte Corner
Byte Corner

Posted on Originally published at bytecorner.dev

An Optional Property Isn't the Same as undefined

undefined Is Not the Same as Not Being There

An optional property looks a lot like a property whose value can be undefined.

But they are not quite the same thing.

That difference becomes important when you care about whether a property exists at all.

🔴 The Problem

Consider these two objects:

const a = {};

const b = {
  value: undefined,
};
Enter fullscreen mode Exit fullscreen mode

At a glance, they can look equivalent.

Reading value gives you undefined in both cases:

console.log(a.value);
console.log(b.value);
Enter fullscreen mode Exit fullscreen mode

Both print:

undefined
Enter fullscreen mode Exit fullscreen mode

But the objects are different.

One does not have a value property.

The other does.

You can see that with:

console.log("value" in a);
console.log("value" in b);
Enter fullscreen mode Exit fullscreen mode

The result is:

false
true
Enter fullscreen mode Exit fullscreen mode

That distinction is easy to miss because normal property access hides it.

🟢 The TypeScript Part

Now look at this type:

type Config = {
  value?: string;
};
Enter fullscreen mode Exit fullscreen mode

The ? means the property may be absent.

So this is valid:

const config: Config = {};
Enter fullscreen mode Exit fullscreen mode

And this is also valid:

const config: Config = {
  value: "hello",
};
Enter fullscreen mode Exit fullscreen mode

Depending on your TypeScript configuration, this can also be valid:

const config: Config = {
  value: undefined,
};
Enter fullscreen mode Exit fullscreen mode

But those last two objects still represent different runtime states.

The first has a value.

The second has a property whose value is undefined.

That difference matters when the presence of the property itself has meaning.

âš¡ The Part That Usually Bites

Imagine an API where omitting a property means:

"Don't change this setting."
Enter fullscreen mode Exit fullscreen mode

while explicitly passing undefined has a different meaning.

Or imagine code that checks whether a property was supplied:

if ("value" in config) {
  // the caller supplied the property
}
Enter fullscreen mode Exit fullscreen mode

Now these two values are no longer interchangeable:

const a: Config = {};

const b: Config = {
  value: undefined,
};
Enter fullscreen mode Exit fullscreen mode

The type might make them look similar.

The runtime object does not.

This becomes especially interesting when objects are passed between functions, merged together, serialized, or used as configuration.

🧠 The TypeScript Detail

There is a compiler option specifically related to this distinction:

{
  "compilerOptions": {
    "exactOptionalPropertyTypes": true
  }
}
Enter fullscreen mode Exit fullscreen mode

With this enabled, an optional property means the property can be omitted.

It does not automatically mean you can explicitly assign undefined.

So:

type Config = {
  value?: string;
};
Enter fullscreen mode Exit fullscreen mode

allows:

const a: Config = {};
Enter fullscreen mode Exit fullscreen mode

and:

const b: Config = {
  value: "hello",
};
Enter fullscreen mode Exit fullscreen mode

But this becomes an error:

const c: Config = {
  value: undefined,
};
Enter fullscreen mode Exit fullscreen mode

If you actually want to allow the property to exist with undefined, say so:

type Config = {
  value?: string | undefined;
};
Enter fullscreen mode Exit fullscreen mode

Now the type describes both possibilities:

property is absent
        OR
property exists with undefined
        OR
property exists with a string
Enter fullscreen mode Exit fullscreen mode

That is a much more precise description of the object.

🧩 When Could This Be Useful?

This distinction is especially useful for configuration and update objects.

Consider:

type UserUpdate = {
  name?: string;
  email?: string;
};
Enter fullscreen mode Exit fullscreen mode

An update function might interpret an omitted property as:

"Leave the existing value alone."
Enter fullscreen mode Exit fullscreen mode

while a present property could mean:

"Change this field."
Enter fullscreen mode Exit fullscreen mode

That makes property presence part of the API's meaning.

The same idea appears when dealing with object merging:

const defaults = {
  color: "orange",
};

const options = {
  color: undefined,
};

const result = {
  ...defaults,
  ...options,
};
Enter fullscreen mode Exit fullscreen mode

The property was not missing.

It was explicitly present.

So the resulting object contains:

{
  color: undefined;
}
Enter fullscreen mode Exit fullscreen mode

That can be very different from simply not providing color at all.

🧠 The Takeaway

An optional property is about presence.

undefined is about value.

Those two concepts often produce the same result when you simply read the property:

object.value;
Enter fullscreen mode Exit fullscreen mode

But they can represent different states.

Once your application cares about whether something was omitted or explicitly provided, that difference stops being a TypeScript technicality.

It becomes part of the API design.

value?: string
Enter fullscreen mode Exit fullscreen mode

does not simply mean:

"value can be undefined"
Enter fullscreen mode Exit fullscreen mode

It starts with:

"this property may not exist"
Enter fullscreen mode Exit fullscreen mode

And sometimes, that is exactly the distinction your code needs.

Top comments (0)