Главная Категории Контакты Поиск

Углубленная модификация свойств типа

Как изменить свойства типа, сделав их required, optional или readonly.

TypeScript·09.04.2020·читать 1 мин 🤓·Автор: Alexey Myzgin

Часто бывает так, что нужно взять существующий тип Person и сделать каждое из его свойств необязательным. Используя mapped types, получим:

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

type Partial<T> = {
  // К каждому свойству типа <T> добавляем знак `?`.
  [P in keyof T]+?: T[P];
};

type PartialPerson = Partial<Person>;

// Теперь type PartialPerson выглядит так:
type PartialPerson = {
  name?: string | undefined;
  age?: number | undefined;
  location?: string | undefined;
};

Также, можно создать тип с полями только для чтения (readonly) или с обязательными полями:

// Сохраняет типы одинаковыми, но делает каждое свойство доступным только для чтения (readonly).
type Readonly<T> = {
  +readonly [P in keyof T]: T[P];
};

// Сохраняет типы одинаковыми, но делает каждое свойство обязательным (required).
type Required<T> = {
  [P in keyof T]-?: T[P];
};

Кроме того, если у тебя есть не обязательные вложенные свойства, например:

interface Person {
  name: string;
  age: number;
  location?: Location;
}

interface Location {
  country: string;
  city?: string;
  street?: string;
}

И ты хочешь сделать все свойства обязательными - можно сделать таким образом:

type DeepRequired<T> = {
  [P in keyof T]-?: DeepRequired<T[P]>;
};

type RequiredPerson = DeepRequired<Person>;

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

Важно! Каждое свойство должно быть типом, иначе DeepRequired не будет работать. Например, как здесь:

interface Person {
  name: string;
  age: number;
  location?: {
    country: string;
    city?: string;
    street?: string;
  };
}

Подробнее о модификаторах перебора типов.

Website, name & logo
Copyright © 2022. Alex Myzgin