TypeScriptJuniorTechnical
Как TypeScript обрабатывает null и undefined? Что такое strict null checking?
При strictNullChecks: true значения null и undefined образуют отдельные типы и не присваиваются другим типам без явного указания. Это исключает целый класс runtime-ошибок и требует явного narrowing перед использованием значения.
null и undefined в TypeScript. Strict null checking
По умолчанию (без строгого режима) TypeScript ведёт себя как JavaScript: значения null и undefined можно присвоить переменной любого типа. Это маскирует целый класс ошибок времени выполнения.
Режим без strictNullChecks
// strictNullChecks: false (поведение по умолчанию без strict)
let name: string = null; // OK — никакой ошибки
let count: number = undefined; // OK
name.toUpperCase(); // ошибка только в runtime!
Включение strictNullChecks
// tsconfig.json
{
"compilerOptions": {
"strict": true // включает strictNullChecks и другие флаги
// или отдельно:
// "strictNullChecks": true
}
}
При включённом strictNullChecks null и undefined образуют собственные типы и не являются подтипами других типов.
Явное указание nullable-типов
let name: string = null; // ошибка!
let name: string | null = null; // OK
let id: number | undefined; // OK — undefined по умолчанию
function findUser(id: number): User | null {
return db.find(u => u.id === id) ?? null;
}
Сужение типов (narrowing)
function greet(name: string | null | undefined) {
// Вариант 1: явная проверка
if (name == null) {
// name: null | undefined
return "Hello, stranger";
}
// name: string
return `Hello, ${name.toUpperCase()}`;
// Вариант 2: optional chaining
// return `Hello, ${name?.toUpperCase() ?? "stranger"}`;
}
Non-null assertion operator (!)
const input = document.getElementById("search")!;
// TypeScript доверяет вам — input: HTMLElement (не null)
input.focus();
// Опасно: если элемент реально отсутствует, runtime-ошибка
Optional chaining и nullish coalescing
type Config = {
db?: {
host?: string;
port?: number;
};
};
function getHost(config: Config): string {
return config.db?.host ?? "localhost";
}
function getPort(config: Config): number {
return config.db?.port ?? 5432;
}
strictPropertyInitialization
Флаг strictPropertyInitialization (входит в strict) требует, чтобы все свойства класса инициализировались в конструкторе.
class UserService {
private db: Database; // ошибка! Не инициализировано в конструкторе
// Решения:
private db!: Database; // non-null assertion (вы уверены)
private db: Database | undefined; // честный nullable
constructor(db: Database) { this.db = db; } // инициализация в ctor
}
Подводные камни
- Non-null assertion (!) злоупотребление: оператор
!полностью отключает проверку в этом месте. Если DOM-элемент реально отсутствует или API вернул null — runtime TypeError неизбежен. - == null vs === null: проверка
x == nullпокрывает оба случая (nullиundefined), что удобно при narrowing. Проверкаx === nullне сужаетundefined. - JSON.parse возвращает any: даже при strictNullChecks TypeScript не поможет с отсутствующими полями в распарсенном JSON — используйте валидацию (zod, valibot) или type guard.
- Массивы и индексный доступ: по умолчанию
arr[i]имеет тип элемента, неT | undefined. ВключитеnoUncheckedIndexedAccessдля защиты. - Опциональные параметры vs | undefined:
foo(x?: string)иfoo(x: string | undefined)похожи, но различаются: первый позволяет не передавать аргумент вообще, второй требует явного undefined. - Ложная безопасность через as:
const x = response.data as Userне проверяет поля — null внутри объекта всё равно пройдёт.
Common mistakes
- Смешивать «
null,undefinedи strict null checking» с похожим механизмом без критерия выбора. - Игнорировать риск: неверно оценить границы применения темы «
null,undefinedи strict null checking» и получить хрупкое решение. - Показывать только синтаксис и не объяснять поведение в runtime или сборке.
What the interviewer is testing
- Объясняет как TypeScript отделяет отсутствующие значения от обычных типов.
- Показывает на примере, как работает: при
strictNullChecksnullиundefinedне входят автоматически в каждый тип, поэтому код обязан явно обработать пустые состояния. - Называет production-нюанс и граничный случай для темы «
null,undefinedи strict null checking».