20 приемов TypeScript, которые должен знать каждый разработчик От Редакция techrocks.ru / 20.02.2025 TypeScript — это мощный инструмент для современной JavaScript-разработки, обеспечивающий типобезопасность и предоставляющий расширенные возможности. Многие разработчики знают основы TypeScript, но знание некоторых приемов может сделать ваш код более эффективным, чистым и поддерживаемым. Давайте рассмотрим эти премы! 1. NonNullable TypeScript предоставляет утилиту NonNullable для исключения null и undefined из типа. Это поможет вам избежать неожиданных нулевых значений. type User = { name: string; age?: number | null };
const user: NonNullable<User["age"]> = 30; // ✅ No null or undefined allowed 2. Использование Partial для гибкости Утилита Partial<T> делает все свойства типа необязательными. Это очень удобно, когда вы обновляете только подмножество полей объекта. interface User {
  name: string;
  age: number;
  email: string;
}

const updateUser = (user: Partial<User>) => {
  // You can pass only the fields you want to update
  return { ...user, updatedAt: new Date() };
};

updateUser({ name: 'John' }); // No need to provide the entire object 3. Использование Readonly для неизменяемых данных Если вам нужна неизменяемость в TypeScript, Readonly<T> сделает все свойства типа неизменяемыми, предотвращая переприсваивание. const config: Readonly<{ apiUrl: string; retries: number }> = {
  apiUrl: 'https://api.example.com',
  retries: 5
};

config.apiUrl = 'https://newapi.com'; // ❌ Error: Cannot assign to 'apiUrl' because it is a read-only property 4. Сопоставленные типы для динамической типизации свойств Сопоставленные типы позволяют создавать новые типы путем преобразования существующих. Это удобно для создания вариаций типа объекта. type Status = 'loading' | 'success' | 'error';
type ApiResponse<T> = {
  [K in Status]: T;
};

const response: ApiResponse<string> = {
  loading: 'Fetching...',
  success: 'Data loaded',
  error: 'Something went wrong'
}; 5. Типы кортежей с опциональными элементами Знаете ли вы, что TypeScript позволяет использовать опциональные элементы в кортежах? Это очень удобно при работе с переменными аргументами функций. type UserTuple = [string, number?, boolean?];

const user1: UserTuple = ['Alice'];          // ✅ Just the name
const user2: UserTuple = ['Bob', 30];        // ✅ Name and age
const user3: UserTuple = ['Charlie', 25, true]; // ✅ Full tuple 6. Union-типы с исчерпывающими проверками Убедитесь, что вы обрабатываете все возможные случаи с помощью union-типов и исчерпывающих проверок в инструкциях switch. type Status = 'open' | 'closed' | 'pending';

function handleStatus(status: Status) {
  switch (status) {
    case 'open':
      return 'Opened';
    case 'closed':
      return 'Closed';
    case 'pending':
      return 'Pending';
    default:
      const exhaustiveCheck: never = status; // ❌ Error if a new status type is added but not handled
      return exhaustiveCheck;
  }
} 7. Тип Omit для исключения ключей Иногда вам нужно создать тип объекта, исключающий определенные ключи. В этом случае Omit — ваш друг! interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Omit<Todo, 'description'>;

const todo: TodoPreview = {
  title: 'Learn TypeScript',
  completed: false
}; 8. Сужение типов с помощью in и instanceof Используйте in и instanceof для сужения типов во время выполнения программы. function processInput(input: string | number | { title: string }) {
  if (typeof input === 'string') {
    return input.toUpperCase(); // Narrowed to string
  } else if (typeof input === 'number') {
    return input * 2; // Narrowed to number
  } else if ('title' in input) {
    return input.title; // Narrowed to object with title property
  }
} 9. Условные типы для расширенной логики типов Условные типы обеспечивают невероятную гибкость при преобразовании типов на основе условий. type IsString<T> = T extends string ? true : false;

type CheckString = IsString<'Hello'>; // true
type CheckNumber = IsString<42>; // false 10. Использование as const для неизменяемых литеральных типов as const отлично подходит для замораживания значений и обеспечения того, чтобы TypeScript рассматривал их как литеральные типы, а не как изменяемые значения. const COLORS = ['red', 'green', 'blue'] as const;

type Color = typeof COLORS[number]; // 'red' | 'green' | 'blue' 11. Extract и Exclude для уточнения типов Используйте Extract и Exclude, чтобы отфильтровать или выбрать определенные типы из объединения. type T = 'a' | 'b' | 'c';
type OnlyAOrB = Extract<T, 'a' | 'b'>; // 'a' | 'b'
type ExcludeC = Exclude<T, 'c'>; // 'a' | 'b' 12. Защитники типа для пользовательской проверки Создавайте собственных защитников типов (type guards) для динамического уточнения типов во время выполнения. function isString(input: any): input is string {
  return typeof input === 'string';
}

const value: any = 'Hello';

if (isString(value)) {
  console.log(value.toUpperCase()); // Safe: value is a string here
} 13. Использование Record для типов динамических объектов Когда вам нужен тип для объекта с динамическими ключами, Record<K, V> — идеальный вариант. type Role = 'admin' | 'user' | 'guest';
const permissions: Record<Role, string[]> = {
  admin: ['read', 'write', 'delete'],
  user: ['read', 'write'],
  guest: ['read']
}; 14. Динамические свойства классов с индексными сигнатурами Индексные сигнатуры позволяют создавать объекты или классы с динамически именуемыми свойствами. class DynamicObject {
  [key: string]: any;
}

const obj = new DynamicObject();
obj.name = 'Alice';
obj.age = 30; 15. Тип never для невозможных состояний Тип never представляет значения, которые никогда не должны встречаться. Он часто используется в исчерпывающих проверках. function assertNever(value: never): never {
  throw new Error(`Unexpected value: ${value}`);
} 16. Опциональные цепочки для безопасного доступа к свойствам Используйте оператор опциональной последовательности (?.) для безопасного доступа к глубоко вложенным свойствам. Это позволит не опасаться ошибок, связанных с undefined. const user = { profile: { name: 'John' } };
const userName = user?.profile?.name; // 'John'
const age = user?.profile?.age ?? 'Not provided'; // Fallback to default 17. Установка значений по умолчанию с помощью оператора нулевого слияния (??) Используйте оператор нулевого слияния, чтобы предоставить запасное значение в том случае, если исходное значение равно null или undefined. const input: string | null = null;
const defaultValue = input ?? 'Default'; // 'Default' 18. Вывод типов возвращаемых значений с помощью ReturnType Утилита ReturnType<T> извлекает тип возвращаемого значения функции. Это может быть полезно, когда вы имеете дело со сложными типами. function getUser() {
  return { name: 'John', age: 30 };
}

type UserReturn = ReturnType<typeof getUser>; // { name: string; age: number; } 19. Параметры типов в функциях Параметры дженерик-типов делают ваши функции гибкими и пригодными для повторного использования в различных типах. function identity<T>(value: T): T {
  return value;
}

identity<string>('Hello'); // 'Hello'
identity<number>(42); // 42 20. Типы пересечения для объединения структур Типы пересечения (intersection types) позволяют объединять несколько типов в один. type Admin = { privileges: string[] };
type User = { name: string };

type AdminUser = Admin & User;

const adminUser: AdminUser = {
  privileges: ['admin', 'editor'],
  name: 'Alice'
}; Эти приемы помогут вам поднять ваши навыки работы с TypeScript на новый уровень! Продолжайте экспериментировать и внедрять эти паттерны в свои проекты, чтобы код был чище и эффективнее. Успешного кодинга! Перевод статьи “20 TypeScript Tricks Every Developer Should Know”. 7 уроков дизайна для разработчиков 1 комментарий / Новости, Обучение / От andrey_av Не документируйте код. Кодируйте документацию 1 комментарий / Новости, Обучение / От andrey_av
==============
В этой статье рассмотрены 20 приемов TypeScript, которые помогут разработчикам писать более эффективный, чистый и поддерживаемый код. Рассмотрены такие темы, как NonNullable, Partial, Readonly, сопоставленные типы, кортежи с опциональными элементами, Union-типы, Omit, сужение типов, условные типы, Extract и Exclude, защитники типов, Record, динамические свойства классов, тип never, опциональные цепочки, операторы нулевого слияния, ReturnType, параметры дженерик-типов и типы пересечения. Цель — предоставить читателям практические инструменты для улучшения качества и эффективности TypeScript-кода.