Объект, возможно, не определен-но это не…?

#typescript

Вопрос:

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

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

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

Но как? Я инициализировал его, чтобы new Set<string> … ?

Я предполагаю , потому что он помечен как nullable/необязательный Metadata , но я полагал, что компилятор увидит, что я действительно инициализировал tags значение.

Комментарии:

1. Вы утверждали , что его тип был из Metadata , чей тип tags является необязательным. Если вы этого не хотели, просто полностью удалите там обозначение типа? const metadata = {

Ответ №1:

Когда TypeScript оценивает ваши типы, он работает с вашим кодом, строка за строкой, сужая тип переменной по ходу.

Если вы использовали:

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

Тип этой постоянной переменной, является:

 {
  tags: Set<string>;
}
 

Однако в той же строке вы говорите TypeScript: «Нет, этот объект является Metadata объектом — относитесь к нему как к таковому», когда используете:

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

Итак, к тому времени, когда TypeScript доберется до проверки этой строки, metadata это Metadata объект, tags свойство которого является необязательным:

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

Поскольку вы понимаете, что только что установили это свойство, вы можете использовать утверждение ! типа, чтобы сказать «это значение не undefined является или null «.

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

Если вы планируете инициализировать каждое свойство metadata , вы можете изменить тип , чтобы сказать «этот объект повторяет форму Metadata , но требуется каждое свойство», используя Required<T> тип утилиты:

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

Что позволит вам использовать свое задание как обычно:

 metadata.tags.add('test');
 

Комментарии:

1. Да, в этом есть смысл. Я надеялся , что, специально установив tags , тип будет выведен как Metadata amp; { tags: Set<string> } . Похоже, компилятор может быть достаточно умен, чтобы понять это-возможно, в будущем! Спасибо.