TypeScript Служебные типы

В TypeScript есть набор служебных типов, которые служат для удобного создания производных типов и обработки типичных задач, возникающих при работе с типами. Они упрощают рутинные операции с типами и позволяют экономить время и усилия при разработке.

Служебные типы являются частью стандарта TypeScript и находятся в глобальном пространстве имён, поэтому доступны без дополнительных импортов.

В этой главе мы рассмотрим наиболее популярные служебные типы.


Partial<Type>

Делает все свойства типа необязательными.

Это полезно, когда нужно создать объект, который частично заполняется пользователями или не обязан содержать все свойства исходного типа.

Пример


interface Person {
  name: string;
  age: number;
}

let partialPerson: Partial<Person> = { name: "John" };
// Теперь partialPerson может не содержать свойство 'age', так как оно стало необязательным.


Required<Type>

Делает все свойства типа обязательными.

Это полезно, когда нужно убедиться, что объект содержит все свойства, даже если изначально тип позволял пропуская некоторые из них.

Пример


interface Product {
  name: string;
  price?: number;
}

let product: Required<Product> = { name: "Phone", price: 500 };
// Теперь свойство 'price' стало обязательным.


Record<KeyType, ValueType>

Создаёт объект с заданными ключами и значениями.

Record позволяет быстро определить тип объекта с заданным типом ключа и значения.

Пример


const nameAgeMap: Record<string, number> = {
  'Alice': 21,
  'Bob': 25
};

// Эквивалентно { [key: string]: number }


Pick<Type, Keys>

Оставляет только указанные свойства типа.

Полезно, когда нужно выбрать подмножество свойств из типа, отбросив остальные.

Пример


interface Address {
  country: string;
  city: string;
  zip: string;
}

let addressInfo: Pick<Address, "city" | "zip"> = { city: "Москва", zip: "123456" };
// Остальные свойства ("country") стали недоступны.


Omit<Type, Keys>

Удаляет указанные свойства из типа.

Противоположность Pick, когда нужно избавиться от определённых свойств.

Пример


interface Task {
  id: number;
  title: string;
  completed: boolean;
}

let taskSummary: Omit<Task, "completed"> = { id: 1, title: "Finish report" };
// Свойство "completed" исключено из типа.


Exclude<Type, ExcludedUnion>

Удаляет из типа элементы, относящиеся к указанному объединению.

Это полезно, когда нужно избавиться от определённых элементов, содержащихся в типе.

Пример


type Pet = "dog" | "cat" | "fish";

let mammalPet: Exclude<Pet, "fish"> = "dog";
// Теперь mammalPet может быть только "dog" или "cat".


ReturnType<FuncType>

Извлекает тип возвращаемого значения из типа функции.

Это полезно, когда нужно извлечь тип возвращаемого значения функции и использовать его отдельно.

Пример


type FetchResponse = () => { success: boolean; data: any };

let response: ReturnType<FetchResponse> = { success: true, data: [] };
// Теперь response имеет тип { success: boolean; data: any }.


Parameters<FuncType>

Извлекает типы параметров функции как массив.

Это может пригодиться, когда нужно явно задекларировать типы параметров функции отдельно.

Пример


type DivideFunc = (a: number, b: number) => number;

let params: Parameters<DivideFunc> = [10, 2];
// Теперь params имеет тип [number, number].


Readonly<Type>

Создаёт новый тип, в котором все свойства становятся только для чтения, то есть их нельзя изменять после присвоения значения.

Учтите, что TypeScript предотвращает изменения на этапе компиляции, но теоретически, так как код компилируется в JavaScript, вы всё ещё можете переопределить свойство, помеченное как readonly.

Пример


interface Config {
  port: number;
  host: string;
}

let config: Readonly<Config> = { port: 8080, host: "localhost" };
// Попытка изменить config.host вызовет ошибку.


NonNullable<Type>

Удаляет из типа значения null и undefined.

Помогает избежать случаев, когда переменная может быть null или undefined, что улучшает безопасность кода.

Пример


type MaybeNumber = number | null | undefined;

let safeNum: NonNullable<MaybeNumber> = 10;
// Теперь safeNum не может быть null или undefined.


Extract<Type, Union>

Извлекает из типа только те элементы, которые относятся к указанному объединению.

Полезно, когда нужно выбрать определённые элементы из типа, основываясь на объединении.

Пример


type Event = "click" | "hover" | "resize";

let eventHandler: Extract<Event, "click" | "hover"> = "click";
// Теперь eventHandler может быть только "click" или "hover".


Как и зачем использовать служебные типы?

Служебные типы решают повседневные задачи типизации, позволяя разработчику:

  • Сделать часть свойств объекта необязательной или доступной только для чтения.
  • Создать подмножество свойств из объекта.
  • Обеспечить строгую типизацию при работе с коллекциями и объектами.
  • Легко формировать тип возвращаемого значения или параметров функции.

Их использование позволяет сильно сократить количество рутинной работы по типизации и делает код более надежным и стабильным.