Как объявить тип, допускающий значение null или undefined в TypeScript?
Объединение типов (Union Types) — основной способ
В TypeScript для объявления типа, который может принимать null или undefined, используется механизм объединения типов (union types). Вы указываете несколько возможных типов через вертикальную черту |.
Чтобы ваша функция принимала number, null и undefined, нужно написать так:
function greetUser(age: number | null | undefined) {
if (age === null || age === undefined) {
console.log('Возраст неизвестен');
} else {
console.log(`Возраст: ${age}`);
}
}
// Теперь все работает без ошибок
greetUser(25); // Возраст: 25
greetUser(null); // Возраст неизвестен
greetUser(undefined); // Возраст неизвестен
Сокращение с помощью "?" (опциональный параметр)
Если вы хотите, чтобы параметр мог отсутствовать (то есть быть undefined при вызове без аргумента), нужно использовать опциональный параметр — знак вопроса ? перед двоеточием:
function greetUser(age?: number) {
// age может быть number или undefined
if (age === undefined) {
console.log('Возраст неизвестен');
} else {
console.log(`Возраст: ${age}`);
}
}
greetUser(25); // Возраст: 25
greetUser(); // Возраст: неизвестен (undefined)
// greetUser(null); // Ошибка! null не допускается
Обратите внимание: ? автоматически добавляет undefined в тип, но null — нет. Если нужно и то, и другое, комбинируйте:
function greetUser(age?: number | null) {
// age: number | undefined | null
}
strictNullChecks — почему это важно
В TypeScript есть флаг компилятора strictNullChecks (обычно включен в strict режиме). Когда он активен, null и undefined не являются частью других типов автоматически. Это заставляет вас явно указывать их в объединении, что делает код безопаснее.
Если отключить эту опцию (не рекомендуется), то можно писать age: number и передавать null — но тогда вы теряете все преимущества типизации.
Практические примеры
- Возврат значений: функция может вернуть
string | null, если поиск не дал результата. - Свойства объектов:
user: { name: string; age?: number | null }— возраст может отсутствовать или быть null. - Тип "maybe": часто используют
type MaybeNumber = number | null | undefined;для переиспользования.
Важно: сужение типа (type narrowing)
Когда вы работаете с объединённым типом, TypeScript заставляет вас проверять, какое именно значение пришло. Используйте условные операторы или typeof:
function process(age: number | null | undefined) {
// Без проверки нельзя использовать age как число
// age.toFixed(2); // Ошибка!
if (typeof age === 'number') {
// Внутри блока age точно number
return age.toFixed(2);
}
return 'Не число';
}
Такой подход предотвращает ошибки времени выполнения, когда вы случайно вызываете методы на null или undefined.
Итог
- Для null и undefined используйте
тип | null | undefined. - Для опциональных параметров используйте
?— он добавляетundefined. - Всегда проверяйте значения перед использованием — это TypeScript-вей.
- Не отключайте
strictNullChecks— это главный защитник от багов с null.
Использование дженериков для создания универсального nullable-типа
Если в вашем проекте часто встречаются nullable-типы, можно создать обобщённый тип-помощник. Это сделает код чище и уменьшит повторения:
type Nullable<T> = T | null | undefined;
// Использование
function greetUser(age: Nullable<number>) {
if (age == null) { // проверка на null и undefined одновременно
console.log('Возраст неизвестен');
} else {
console.log(`Возраст: ${age}`);
}
}
Обратите внимание на age == null (с двумя равно) — это JavaScript-трюк, который проверяет и null, и undefined одновременно, что очень удобно в таких случаях.
Альтернатива: Non-null assertion operator (!)
Иногда вы точно знаете, что значение не null/undefined, но TypeScript не может это вывести. Используйте оператор ! (non-null assertion) для подавления ошибки:
function getLength(str: string | null): number {
// Мы уверены, что str не null, хотя TypeScript не уверен
return str!.length; // "!" говорит: "доверься мне, это не null"
}
Предупреждение: используйте ! только когда абсолютно уверены, иначе рискуете получить runtime-ошибку. Это костыль, а не решение.
Когда использовать что
- Union types (|) — стандартный, безопасный подход.
- Nullable<T> — для частого повторения.
- Опциональные параметры (?) — для отсутствующих аргументов.
- Non-null assertion (!) — только в крайних случаях, когда вы контролируете логику.
Выбирайте первый вариант как основной, а остальные — по необходимости.