TypeScript Utility Types — вспомогательные типы и области их применения



В статье расскажу, что такое Utility Types в TypeScript, расскажу про основные вспомогательные типы, и покажу, как применять их на реальных проектах.
Вспомогательные типы (utility types) TypeScript - это набор встроенных generic-типов, которые можно использовать для преобразования или манипулирования другими типами.
Какие существуют вспомогательные типы
Partial
Partial<Type>
— этот вспомогательный тип создает новый тип, делая все свойства исходного типа опциональными.
interface User {
name: string;
age: number;
email: string;
}
type PartialUser = Partial<User>;
// Result: { name?: string; age?: number; email?: string; }
const user: User = {
name: 'Peter',
age: 30,
email: 'peter@gmail.com'
}
const partialUser: PartialUser = {
email: 'user@gmail.com'
}
Required
Required<Type>
— создает новый тип, делая все свойства исходного типа обязательными.
interface User {
name?: string;
age?: number;
email?: string;
}
type RequiredUser = Required<User>;
// Result: { name: string; age: number; email: string; }
const user: User = {
name: 'Peter',
}
const partialUser: RequiredUser = {
name: 'user',
age: 18,
email: 'user@gmail.com'
}
Readonly
Readonly<Type>
— создает новый тип, делая все свойства исходного типа доступными только для чтения, но не для модификации.
interface User {
name: string;
age: number;
email: string;
}
type ReadonlyUser = Readonly<User>;
// Result: { readonly name: string; readonly age: number; readonly email: string; }
const user: User = {
name: 'Peter',
age: 30,
email: 'peter@gmail.com'
}
user.name = 'Sveta';
const strictUser: ReadonlyUser = {
name: 'user',
age: 18,
email: 'user@gmail.com'
}
strictUser.name = 'Andrey'; // Cannot assign to 'name' because it is a read-only property.
Pick
Pick<Type, Keys>
— создает новый тип путем выбора набора свойств из исходного типа на основе параметра Keys
.
interface User {
name: string;
age: number;
email: string;
}
type UserSocial = Pick<User, 'name' | 'email'>;
// Result: { name: string; email: string; }
const userSocial: UserSocial = {
name: "Vlad",
email: 'vadiyha@list.ru'
}
Omit
Omit<Type, Keys>
— создает новый тип путем исключения набора свойств из исходного типа на основе параметра Keys
interface User {
name: string;
age: number;
email: string;
}
type UserSocial = Omit<User, 'age'>;
// Result: { name: string; email: string; }
const userSocial: UserSocial = {
name: "Vlad",
email: 'vadiyha@list.ru'
}
Parameters
Parameters<T>
— создает tuple type из типов, используемых в параметрах функции типа T
type FuncParams0 = Parameters<(s: string) => void>; // [s: string]
function myFunction(name: string, age: number): string {
return 'Hello, world!';
}
type FuncParams1 = Parameters<typeof myFunction>; // [name: string, age: number]
ReturnType
ReturnType<T>
— создает тип, состоящий из возвращаемого типа функции Type.
type MyFunctionReturnType1 = ReturnType<() => number>; // type is 'number'
function myFunction(): string {
return 'Hello, world!';
}
type MyFunctionReturnType = ReturnType<typeof myFunction>; // type is 'string'
Exclude
Exclude<Type, ExcludedUnion>
— создает новый тип путем исключения из типа любых типов в ExcludedUnion
из Type
.
type MyUnion = 'a' | 'b' | 'c' | 'd';
type MyExcludedType = Exclude<MyUnion, 'a' | 'b'>;
// Result: 'c' | 'd'
const firstLetter: MyUnion = 'a';
// const secondLetter: MyExcludedType = 'b'; // Type '"b"' is not assignable to type 'MyExcludedType'
const lastLetter: MyExcludedType = 'd';
Record
Record<KeyType, ValueType>
— создает новый тип с набором свойств, определяемых KeyType
, и соответствующим типом значения, определяемым ValueType
interface User {
name: string;
age: number;
email: string;
}
type UserRecord = Record<string, User>;
// Result: { [x: string]: User }
const users: UserRecord = {
userOne: {
name: 'Peter',
age: 50,
email: 'peter@mail.ru',
},
userTwo: {
name: 'Vladlena',
age: 89,
email: 'edinorozhka@mail.ru',
}
}
Примеры с реальных проектов
Библиотека React имеет собственные вспомогательные типы, которые базируются на TypeScript utlity types:
React.ComponentPropsWithRef
используетPartial<T>
, чтобы сделать все свойства опциональнымиReact.FC
используетRequired<T>
, чтобы сделать все свойства обязательными
interface MyProps {
name: string;
age: number;
address: string;
}
type MyPropsPartial = Partial<MyProps>;
type MyPropsRequired = Required<MyProps>;
Менеджер состояния Redux использует Record для определения стандартного корневого состояния:
type DefaultRootState = Record<string, any>;
В каких случаях утилитраные типы могут помочь на вашем проекте:
- Типы
Props
иState
: чтобы изменить тип свойств объекта, можно использоватьPartial
,Required
,Pick
иOmit
.
import React, { FC } from 'react';
type Props = {
foo?: string;
}
const MyComponent: FC<Props> = ({ foo = 'default' }) => {
return (
<div>{foo}</div>
);
}
type RequiredProps = Required<Props>; // { foo: string }
type OptionalProps = Partial<Props>; // { foo?: string }
type OmittedProps = Omit<Props, 'foo'>; // {}
export default MyComponent;
- Параметры функци и
Return Types
: при определении параметров функций и типов возвращаемых значений могут пригодитьсяReturnType
,Parameters
иRequired
type MyObject = {
foo: string;
bar: number;
}
function myFunction(param1: string, param2: number): MyObject {
return {
foo: param1,
bar: param2,
};
}
type ReturnTypeExample = ReturnType<typeof myFunction>; // { foo: string, bar: number }
type ParametersExample = Parameters<typeof myFunction>; // [string, number]
type RequiredParamsExample = Required<Parameters<typeof myFunction>>; // [string, number]
Generic
типы: вспомогательные типы можно использовать вместе с generic типами для создания многократно используемого кода, который является гибким и адаптируемым. Например, вы можете использоватьPick
иExclude
для создания общего типа, который извлекает из объекта определенные свойства и исключает другие.
type MyObject = {
foo: string;
bar: number;
baz: boolean;
}
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
}
type MyExclude<T, U> = T extends U ? never : T;
type MyNewObject = MyPick<MyObject, 'foo' | 'baz'>; // { foo: string, baz: boolean }
type MyExcludedObject = MyExclude<keyof MyObject, 'bar'>; // 'foo' | 'baz'
Итого
- Вспомогательные типы часто используются на реальных проектах, в частности, в различных библиотеках React;
- Для работы с объектами чаще всего используются
Partial
,Required
,Pick
иOmit
; - Для работы с функциями —
ReturnType
,Parameters
иRequired
;