Примитивные типы
Базовые типы данных TypeScript: string, number, boolean, null, undefined, void, never, symbol, bigint.
Зачем нужно
- Примитивные типы — фундамент системы типов TypeScript
- Они описывают самые базовые значения и позволяют компилятору ловить простейшие ошибки
- Понимание различий между
null,undefined,voidиneverкритично для написания корректного кода
Где используется
- Аннотации переменных, параметров функций и возвращаемых значений
- Составные типы (union, intersection) строятся из примитивных
- Generics и utility types оперируют примитивными типами
Предпосылки
- Что такое TypeScript — что такое TS и как работает
- Знание примитивных типов JavaScript
string
Строковые значения — одинарные, двойные кавычки или template literals:
let name: string = "Alice";
let greeting: string = 'Hello';
let message: string = `Welcome, ${name}!`;
// Ошибка:
let broken: string = 42;
// Error: Type 'number' is not assignable to type 'string'
number
Все числа — целые и дробные, включая Infinity, NaN, hex, octal, binary:
let age: number = 30;
let price: number = 19.99;
let hex: number = 0xff;
let binary: number = 0b1010;
let octal: number = 0o744;
let negative: number = -42;
let inf: number = Infinity;
let notANumber: number = NaN; // Технически number
// Ошибка:
let broken: number = "42";
// Error: Type 'string' is not assignable to type 'number'
boolean
Только true или false:
let isActive: boolean = true;
let isAdmin: boolean = false;
// Ошибка:
let broken: boolean = 0;
// Error: Type 'number' is not assignable to type 'boolean'
// Truthy/falsy — это JS-концепция, TS различает boolean и другие типы
if (isActive) {
// ...
}
null и undefined
Два отдельных типа, каждый с единственным значением:
let nothing: null = null;
let notDefined: undefined = undefined;
// С strictNullChecks: true (рекомендуется!)
let name: string = null; // Ошибка!
let age: number = undefined; // Ошибка!
// Нужно явно указать что значение может быть null/undefined
let name: string | null = null; // OK
let age: number | undefined = undefined; // OK
// Без strictNullChecks — null и undefined присваиваются любому типу (опасно!)
Опциональные свойства и параметры
// Опциональное свойство — автоматически добавляет | undefined
interface User {
name: string;
age?: number; // number | undefined
}
// Опциональный параметр
function greet(name: string, title?: string): string {
// title: string | undefined
return title ? `${title} ${name}` : name;
}
void
Отсутствие возвращаемого значения у функции:
// Функция ничего не возвращает
function log(message: string): void {
console.log(message);
}
// void допускает return без значения
function doSomething: void {
if (Math.random > 0.5) {
return; // OK
}
// неявный return — OK
}
// void переменная может быть только undefined
let v: void = undefined;
let v2: void = null; // Ошибка с strictNullChecks
void в callback-ах
// Важный нюанс: void в callback означает "возвращаемое значение игнорируется"
type Callback = (item: string) => void;
const items: string = ["a", "b", "c"];
// Array.push возвращает number, но это OK
// потому что forEach ожидает callback с void
items.forEach((item) => items.push(item.toUpperCase()));
never
Тип значения, которое никогда не возникнет:
// Функция, которая НИКОГДА не завершается
function throwError(message: string): never {
throw new Error(message);
}
// Бесконечный цикл
function infiniteLoop: never {
while (true) {
// ...
}
}
// never в exhaustive checks
type Shape = "circle" | "square" | "triangle";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return Math.PI;
case "square":
return 1;
case "triangle":
return 0.5;
default:
// Если добавить новый shape и забыть case — ошибка компиляции
const _exhaustive: never = shape;
throw new Error(`Unknown shape: ${shape}`);
}
}
symbol
Уникальный и неизменяемый идентификатор:
let sym1: symbol = Symbol;
let sym2: symbol = Symbol("description");
// Каждый symbol уникален
console.log(sym1 === sym2); // false
// unique symbol — для констант
const MY_KEY: unique symbol = Symbol("MY_KEY");
// Используется как ключ объекта
const obj = {
[MY_KEY]: "secret value",
};
// Well-known symbols
class MyIterable {
*[Symbol.iterator] {
yield 1;
yield 2;
yield 3;
}
}
bigint
Целые числа произвольной точности (ES2020+):
let big: bigint = 100n;
let huge: bigint = BigInt(9007199254740991);
// Арифметика только между bigint
let sum: bigint = 100n + 200n; // OK
let mixed = 100n + 200; // Ошибка! Нельзя смешивать bigint и number
// Сравнение с number допустимо
console.log(100n === 100); // Ошибка (строгое равенство разных типов)
console.log(100n == 100); // OK: true (нестрогое)
console.log(100n > 50); // OK: true
Сводная таблица
| Тип | Значения | Пример |
|---|---|---|
string |
Текст | "hello", 'world', `${x}` |
number |
Числа (64-bit float) | 42, 3.14, NaN, Infinity |
boolean |
true / false | true, false |
null |
Намеренное отсутствие | null |
undefined |
Значение не задано | undefined |
void |
Нет возвращаемого значения | function f: void {} |
never |
Никогда не возникает | throw, бесконечный цикл |
symbol |
Уникальный идентификатор | Symbol("key") |
bigint |
Большие целые числа | 100n, BigInt(999) |
Вывод типов для примитивов
// TypeScript выводит типы автоматически
let x = "hello"; // string
let y = 42; // number
let z = true; // boolean
// const сужает тип до литерала
const a = "hello"; // "hello" (литеральный тип, не string)
const b = 42; // 42 (не number)
const c = true; // true (не boolean)
Частые ошибки
- Путать
Stringиstring— используйтеstring(маленькая буква).String— это wrapper object
// ПРАВИЛЬНО — примитивный тип
let name: string = "Alice";
// НЕПРАВИЛЬНО — object wrapper
let name: String = "Alice"; // Работает, но не рекомендуется
- Забывать про
strictNullChecks— без негоnullиundefinedсовместимы со всем - Путать
voidиundefined—voidиспользуется для функций,undefined— для значений - Не использовать
neverдля exhaustive checks — пропуск case в switch не обнаружится - Использовать
numberдля bigint — это разные типы, нельзя смешивать
Практика
- Объявите переменные каждого примитивного типа с явными аннотациями
- Попробуйте присвоить
nullпеременной типаstring— включитеstrictNullChecks - Напишите функцию, которая возвращает
never(выбрасывает ошибку) - Создайте exhaustive switch с
never— добавьте новый вариант и увидьте ошибку - Поэкспериментируйте с
constvsletи обратите внимание на вывод типов
Связанные темы
- any unknown never void — подробнее про специальные типы
- Литеральные типы — литеральные варианты примитивов
- Union и Intersection — комбинирование типов
- Type guards — сужение типов в рантайме