Топ ошибок начинающих TypeScript разработчиков
TypeScript — это мощный инструмент, который помогает писать более надёжный и поддерживаемый код. Однако, как и любой язык, он таит в себе ловушки, особенно для новичков. Многие разработчики приходят из JavaScript и продолжают использовать старые привычки, сводя на нет преимущества статической типизации. В этой статье мы разберём 4 самые частые ошибки начинающих TypeScript разработчиков, покажем, как их исправить, и дадим практические советы. Если вы только начинаете свой путь с TypeScript, эта статья поможет вам избежать типичных граблей.
1. Злоупотребление типом any
Самая распространённая ошибка — использование any везде, где TypeScript не может вывести тип автоматически. Начинающие часто пишут так:
function processData(data: any) {
console.log(data.name.toUpperCase());
}
Это полностью отключает проверку типов для переменной data. Вы теряете все преимущества TypeScript: автодополнение, проверку на ошибки и документацию кода.
Что делать вместо этого?
Всегда старайтесь явно описать тип, даже если он сложный. Используйте unknown, если тип действительно неизвестен на момент написания кода:
function processData(data: unknown) {
if (typeof data === 'object' && data !== null && 'name' in data) {
console.log((data as { name: string }).name.toUpperCase());
}
}
Или, ещё лучше, опишите интерфейс:
interface DataItem {
name: string;
age?: number;
}
function processData(data: DataItem) {
console.log(data.name.toUpperCase());
}
Совет: Настройте noImplicitAny: true в tsconfig.json. Компилятор будет ругаться на любое неявное any, и вы привыкнете писать типы.
2. Игнорирование strictNullChecks
В JavaScript null и undefined — это обычные значения. В TypeScript без строгих проверок вы можете случайно обратиться к свойству null и получить ошибку в рантайме. Типичная ошибка:
function getLength(str: string | null) {
return str.length; // Ошибка: Object is possibly 'null'
}
Если strictNullChecks выключен, TypeScript не предупредит вас, и ошибка проявится только в рантайме.
Решение: Включите strict: true в tsconfig.json. Это автоматически активирует strictNullChecks. Теперь TypeScript заставит вас обрабатывать null и undefined:
function getLength(str: string | null): number {
if (str === null) {
return 0;
}
return str.length;
}
// Или используйте optional chaining и nullish coalescing:
function getLengthSafe(str: string | null): number {
return str?.length ?? 0;
}
Важно: Никогда не отключайте strictNullChecks. Это одна из главных фич TypeScript, которая предотвращает миллионы багов.
3. Неправильная работа с async/await и промисами
TypeScript строго типизирует асинхронные функции, но новички часто забывают про возвращаемый тип Promise. Пример ошибки:
async function fetchUser(id: number) {
const response = await fetch(`/api/users/${id}`);
return response.json(); // TypeScript может не знать точный тип
}
Здесь response.json() возвращает Promise<any>, и вы снова теряете типизацию. Вторая распространённая проблема — забыть обработать ошибки:
async function loadData() {
const data = await fetchUser(1); // Если fetch упал, ошибка не обработана
console.log(data.name);
}
Как правильно?
Всегда явно указывайте возвращаемый тип асинхронной функции и обрабатывайте ошибки:
interface User {
id: number;
name: string;
}
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json() as Promise<User>;
}
async function loadData() {
try {
const data = await fetchUser(1);
console.log(data.name);
} catch (error) {
console.error('Failed to load user:', error);
}
}
Используйте дженерики для типизации ответов от API — это сделает код предсказуемым.
4. Избыточная или недостаточная типизация
Новички часто впадают в крайности: либо пишут типы везде, где можно и нельзя, либо вообще их не пишут. Пример избыточности:
const num: number = 5; // Избыточно, TypeScript сам выведет number
const add = (a: number, b: number): number => a + b; // Возвращаемый тип можно не указывать
С другой стороны, недостаточная типизация проявляется в функциях, где параметры имеют тип any или объекты не описаны интерфейсами.
Золотое правило: Позволяйте TypeScript выводить типы там, где это очевидно (примитивы, простые выражения), но всегда явно типизируйте:
- Параметры функций
- Возвращаемые типы публичных функций (для документации)
- Сложные структуры данных (интерфейсы, типы)
- Границы модулей (экспортируемые функции и классы)
Пример хорошего баланса:
interface Config {
url: string;
timeout?: number;
}
function createConnection(config: Config): Connection {
// TypeScript выведет тип возвращаемого значения из реализации
return new Connection(config.url, config.timeout ?? 5000);
}
Используйте typeof и keyof для динамической типизации, но не злоупотребляйте сложными дженериками, пока не освоите базу.
Заключение
TypeScript создан, чтобы помогать разработчику, а не мешать. Избегая этих четырёх ошибок — злоупотребления any, игнорирования strictNullChecks, неправильной работы с асинхронностью и дисбаланса в типизации — вы сделаете свой код надёжнее, чище и