Базовые типы

Базовые типы

Технический фундамент вывода типов

TypeScript не только читает аннотации, но и активно выводит типы автоматически:

  • const обычно фиксирует более узкий literal-тип;
  • let чаще приводит к расширенному типу (widening);
  • инициализатор влияет на будущий контракт переменной;
  • явная аннотация особенно полезна на границах модулей и в публичных API.

Практический вывод: чем точнее исходная аннотация или инициализация, тем меньше "размытия" типов дальше по коду.

Мини-пример const/let, widening и as const:

const role1 = 'admin'; // тип: "admin" (literal)
let role2 = 'admin'; // тип: string (widening)

const user1 = { role: 'admin' }; // тип: { role: string } (поле можно менять)
const user2 = { role: 'admin' } as const; // тип: { readonly role: "admin" }

const point1 = [10, 20]; // тип: number[]
const point2 = [10, 20] as const; // тип: readonly [10, 20]

Смотри, что важно: const фиксирует ссылку на объект/массив, но не делает вложенные поля неизменяемыми. Если важно сохранить literal-типы и получить readonly-поведение для литерала, используется as const.

Почему базовые типы это фундамент

Если в TypeScript неправильно задана база типов, все остальные преимущества быстро теряются. Базовые типы задают контракты для переменных, аргументов и результатов функций. Это первый фильтр против ошибок "не тот формат данных".

Ключевой момент: чем точнее базовый тип, тем раньше ты ловишь проблему.

Проверь себя: почему any убирает большую часть пользы TypeScript?

Основные примитивные типы

Чаще всего ты используешь:

  • string;
  • number;
  • boolean;
  • null;
  • undefined;
  • bigint;
  • symbol.
let userName: string = 'Anna';
let age: number = 25;
let isAdmin: boolean = false;

Смотри, что важно: TypeScript часто умеет вывести тип сам (type inference), но явные аннотации полезны на границах API и в публичных функциях.

Массивы и кортежи

Массивы можно описывать двумя способами:

const scores: number[] = [10, 20, 30];
const tags: Array<string> = ['js', 'ts'];

Кортеж (tuple) фиксирует длину и типы по позициям.

const point: [number, number] = [10, 20];

Здесь часто путаются: number[] это "любой длины список чисел", а [number, number] это строго два числа.

Проверь себя: подойдет ли number[] для координаты, где обязательно ровно две оси?

any, unknown, void, never

  • any - отключает проверку типов (использовать осторожно).
  • unknown - "неизвестный тип", требует проверки перед использованием.
  • void - отсутствие полезного возвращаемого значения.
  • never - функция не возвращает управление (например, всегда кидает ошибку).
function logMessage(msg: string): void {
  console.log(msg);
}

function fail(message: string): never {
  throw new Error(message);
}

unknown безопаснее any, потому что заставляет сузить тип перед использованием.

function printValue(value: unknown) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase());
  }
}

Union-типы

Union позволяет переменной принимать несколько типов.

let id: string | number;
id = 10;
id = 'user-10';

Это полезно, когда вход реально бывает в нескольких форматах.

Мини-сценарий: API возвращает id как number в одной версии и как string в другой.

Реальные микро-сценарии

  1. Форма профиля.

email: string, age: number | null, isSubscribed: boolean.

  1. Параметр маршрута.

productId: string | number до нормализации.

  1. Логгер.

message: unknown на входе и безопасное сужение перед обработкой.

Частые ошибки новичков

  • Использовать any вместо продуманного union/unknown.
  • Путать null и undefined в контрактах.
  • Игнорировать кортежи там, где важен фиксированный формат.
  • Писать слишком широкие типы, которые не защищают от ошибок.

Анти-провал: если не уверен, начни с unknown и постепенно уточни типы через проверки.

Что будет, если изменить входные данные

Если функция ожидает number, а ей передают '42', TypeScript сразу сообщит о несоответствии. Если тип был string | number, придется явно решить, как обрабатывать оба случая. Это делает бизнес-логику прозрачной, а не скрытой в неявных преобразованиях.

Проверь себя: когда union полезен, а когда он слишком размывает контракт?

Краткий итог

  • Базовые типы в TypeScript формируют основу безопасного кода.
  • string, number, boolean и массивы покрывают большинство повседневных сценариев.
  • unknown обычно лучше any для безопасного старта с неизвестными данными.
  • Union-типы полезны для реальных многовариантных входов.
  • Точность типа на раннем этапе уменьшает количество багов на поздних стадиях.