Почему TS сообщает что возможен undefined?

TypeScript сообщает об возможности значения "undefined" в нескольких случаях. Давайте разберем каждый случай подробнее.

1. Необязательные параметры и свойства.
В TypeScript есть возможность объявлять параметры функции или свойства объекта как необязательные путем добавления знака вопроса (?) после имени параметра или свойства. Это означает, что эти параметры или свойства могут быть не указаны при вызове функции или создании объекта, в результате чего их значения будут равны "undefined".

Пример:

function printName(firstName: string, lastName?: string) {
  console.log(firstName);
  console.log(lastName); // может быть undefined
}
printName("John", "Doe"); // "John" "Doe"
printName("John"); // "John" undefined

2. Неопределенные переменные и свойства.
Если вы объявляете переменную или свойство без явного указания значения, TypeScript будет считать, что эти значения могут быть "undefined", если они не инициализированы в последующем коде.

Пример:

let age: number;
console.log(age); // undefined

class Person {
  name: string;
}
const person = new Person();
console.log(person.name); // undefined

3. TypeScript inference (вывод типов).
Иногда TypeScript не может точно определить тип значения, например, когда вы используете условные операторы или асинхронные функции. В таких случаях TypeScript будет считать, что значение может быть "undefined".

Пример:

function getLength(str: string | undefined) {
  if (str) { // TypeScript понимает, что значение "undefined" возможно
    return str.length;
  }
  return 0;
}

4. Возможность значения "null".
TypeScript также позволяет указывать тип "null" как альтернативу для других типов. В таких случаях TypeScript будет считать, что значения могут быть и "undefined", и "null".

Пример:

let address: string | null = null;
console.log(address); // null

function search(name: string): string | null {
  // некоторая логика поиска
  return null; // результат может быть и "null"
}

В целом, TypeScript сообщает о возможности значения "undefined" для обеспечения безопасности типов и предотвращения ошибок во время выполнения. Это помогает разработчикам обнаруживать потенциальные ошибки связанные с отсутствием значения в переменной или свойстве.