Type guards и сужение
Type guard — это проверка, которая сужает тип. TypeScript понимает такие проверки и даёт доступ к специфичным полям.
typeof
function print(value: string | number) {
if (typeof value === 'string') {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
Работает с string, number, boolean, symbol, undefined, object, function.
in
Проверяет наличие свойства:
type User = { name: string };
type Admin = { name: string; role: string };
function print(person: User | Admin) {
if ('role' in person) {
console.log(person.role);
}
}
instanceof
Для классов:
class Dog { bark() {} }
class Cat { meow() {} }
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
Литеральный дискриминатор
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number };
function area(shape: Shape) {
if (shape.kind === 'circle') {
return Math.PI * shape.radius ** 2;
}
return shape.side ** 2;
}
Пользовательские type guards
Функция, возвращающая value is Type:
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function print(value: unknown) {
if (isString(value)) {
console.log(value.toUpperCase());
}
}
Возвращаемый тип value is string сообщает TypeScript, что при true тип — string.
Проверка на null
function print(user: User | null) {
if (user !== null) {
console.log(user.name);
}
}
Или через опциональную цепочку:
console.log(user?.name);
Или через нулевое слияние:
const name = user?.name ?? 'Гость';
Проверка на undefined
if (value !== undefined) {
//
}
if (typeof value !== 'undefined') {
//
}
Array.isArray
function print(value: string | string[]) {
if (Array.isArray(value)) {
value.forEach((v) => console.log(v));
} else {
console.log(value);
}
}
Assertion functions
Функция, которая выбрасывает исключение, если условие не выполнено:
function assert(condition: unknown, message: string): asserts condition {
if (!condition) throw new Error(message);
}
function print(value: string | null) {
assert(value !== null, 'Value is null');
console.log(value.toUpperCase()); // value: string
}
asserts condition — после вызова TypeScript уверен в условии.
Исключающие проверки
type Status = 'idle' | 'loading' | 'success';
function handle(status: Status) {
if (status === 'idle') return;
if (status === 'loading') return;
// здесь status: 'success'
}
Проблема truthiness
function print(value: string | null) {
if (value) { // отсекает не только null, но и ''
//
}
}
Если пустая строка валидна — проверяй явно:
if (value !== null) {
//
}
Итоги
- Type guards сужают тип
typeof,in,instanceof- Дискриминатор — по литеральному полю
- Пользовательские —
value is Type asserts— для проверок?.и??для null/undefined