Josh M.
Josh M.

Reputation: 27831

Object is possibly undefined -- but it's not...?

type Metadata = {
  tags?: Set<string>;
};

const metadata: Metadata = {
  tags: new Set<string>(),
};

metadata.tags.add('test'); // <-- Object is possibly 'undefined'.ts(2532)

But how? I've initialized it to new Set<string> ... ?

I assume because it is marked as nullable/optional in Metadata, but I figured the compiler would see that I had indeed initialized tags with a value.

Upvotes: 0

Views: 199

Answers (1)

samthecodingman
samthecodingman

Reputation: 26296

When TypeScript evaluates your types, it works down your code, line by line, narrowing the type of the variable as it goes.

If you used:

const metadata = {
  tags: new Set<string>(),
};

The type of this constant variable, is:

{
  tags: Set<string>;
}

However, on that same line, you tell TypeScript, "no, this object is a Metadata object - treat it as such" when you use:

const metadata: Metadata = {
  tags: new Set<string>(),
};

So, by the time TypeScript gets to checking this line, metadata is a Metadata object, where the tags property is optional:

metadata.tags.add('test'); // metadata.tags is possibly 'undefined'

Because you understand that you've just set this property, you can use the ! type assertion to say "this value is not undefined or null".

metadata.tags!.add('test');

If you plan to initialize each property in metadata, you can mutate the type to say "this object follows the shape of Metadata, but each property is required" using the Required<T> utility type:

const metadata: Required<Metadata> = {
  tags: new Set<string>(),
};

Which will allow you to use your assignment as normal:

metadata.tags.add('test');

Upvotes: 2

Related Questions