7 советов по улучшению навыков работы с типами

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

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

  • Generics
  • Шаблонный литерал
  • Индексированные типы доступа
  • Утилитарные типы
  • Операторы KeyOf/TypeOf
  • Условные типы
  • Сопоставленные типы

В процессе обучения для каждого случая будут использоваться текущие примеры:


type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

Вход в полноэкранный режим Выход из полноэкранного режима
  • Обратите внимание, что представленная информация не является полной, так как не предназначена для этого, и в ней описаны только самые популярные случаи использования. Полную информацию, которая охватывает 100% темы, вы можете найти на официальном сайте TS.

А теперь давайте начнем с…

Дженерики

Основная цель дженериков — обеспечить возможность повторного использования.

Давайте разберемся в этом на примере нашего Todo.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Здесь дженерики не используются, и каждое свойство имеет свой определенный тип.
А здесь дженерик реализован:

type FirstTodo<T> = {
   text: T,
   type: "very urgent" |"urgent" | "not urgent",
   daysToFinish: number,
   isFinished: boolean
}
Вход в полноэкранный режим Выход из полноэкранного режима

Что означает T?
T — это треугольные скобки, определяющие тип, и текст имеет такой же тип T.

Например, мы хотим задать тип string для свойства text (это логично) и у нас нет проблем с TS.

const firstTodo: FirstTodo<string> = {
   text: "first todo",
   type: "urgent",
   daysToFinish: 6,
   isFinished: false
}
Вход в полноэкранный режим Выход из полноэкранного режима

А теперь добавим дженерики для каждого из свойств:

type SecondTodo<S, T, N, B> = {
   text: S,
   type: T,
   daysToFinish: N,
   isFinished: B
}

type TypeOptions = "very urgent" |"urgent" | "not urgent"

const secondTodo: SecondTodo<string, TypeOptions, number, boolean> = {
   text: "first todo",
   type: "urgent",
   daysToFinish: 6,
   isFinished: false
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Здесь мы также зададим логические типы для каждого свойства, но, например, для B мы зададим не boolean, а число, которое будет означать, что «isFinished» должно быть равно числу. Также и для «T» мы задаем его собственный пользовательский тип, который может быть изменен на другой тип.

Шаблонный литерал

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

type UrgencyRate = "very " | "" | "not "

type ThirdTodo<T> = {
   text: T,
   type: `${UrgencyRate}urgent`,
   daysToFinish: number,
   isFinished: boolean
}

const thirdTodo: ThirdTodo<string> = {
   text: "third todo",
   type: "not urgent",
   daysToFinish: 6,
   isFinished: false
}
Вход в полноэкранный режим Выход из полноэкранного режима

Типы индексированного доступа

С помощью Indexed Access мы можем создать тип, который может получить доступ к свойству другого типа, заключив одно (или несколько) имен свойств в квадратные скобки.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

type TodoText = Todo["text"] // string

type TodoTextAndIsFinished = Todo["text" | "isFinished"] // string | boolean

Вход в полноэкранный режим Выйти из полноэкранного режима

С помощью оператора keyOf получить все типы свойств для 1 элемента.

type AllTypes = Todo[keyof Todo] // string | number | boolean
Войти в полноэкранный режим Выйти из полноэкранного режима

А с помощью оператора typeOf мы можем получить тип.

typeof "todo" // console.log -> string
Войти в полноэкранный режим Выйти из полноэкранного режима

Это способ создания нового типа в соответствии с текущим элементом.


const forthTodo: Todo = {
  text: "forth todo",
  type: "not urgent",
  daysToFinish: 6,
  isFinished: false
}

type AllTodoTypes = typeof forthTodo

// type AllTodoTypes = {
//   text: string;
//  type: "very urgent" | "urgent" | "not urgent";
//   daysToFinish: number;
//   isFinished: boolean;
}

Вход в полноэкранный режим Выход из полноэкранного режима

Типы утилит

Мы рассмотрим только 6 типов утилиты, это Required, Readonly, Partial, Record, Pick, Omit и NonNullable.

Readonly не позволяет изменять объект извне.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

const fifthTodo: Readonly<Todo> = {
  text: "fifth todo",
  type: "not urgent",
  daysToFinish: 6,
  isFinished: false
}

fifthTodo.text = "new text" // Cannot assign to 'text' because it is a read-only property.

Вход в полноэкранный режим Выход из полноэкранного режима

Требуемый и частичный (Required vs Partial)

Required и Partial определяют, являются ли все свойства типа обязательными.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

const todoWithRequired: Required<Todo> = {
   text: "todo",
   type: "very urgent",
   daysToFinish: 10,
   isFinished: true
}

const todoWithPartial: Partial<Todo> = {
   text: "todo",
   type: "very urgent"
}
Войти в полноэкранный режим Выход из полноэкранного режима

Record (Запись) — это конструктор, который помогает создать новый тип как объект свойств и типов.

type TodosText = "first todo" | "second todo"

type TodoDescription = {
   type: "very urgent" |"urgent" | "not urgent",
   daysToFinish: number,
   isFinished: boolean
}

const todos: Record<TodosText, TodoDescription> = {
   "first todo": {
       type: "not urgent",
       daysToFinish: 10,
       isFinished: false
   },
   "second todo": {
       type: "urgent",
       daysToFinish: 0,
       isFinished: false
   }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Pick и Omit (Pick vs Omit)
Они помогают создать новый тип, выбирая/опуская свойства.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

type todoWithPick = Pick<Todo, "text" | "isFinished">

const todoPick: todoWithPick  = {
   text: "todo",
   isFinished: true
}

type todoWithOmit = Omit<Todo, "isFinished">

const todoOmit: todoWithOmit = {
   text: "todo",
   type: "not urgent",
   daysToFinish: 40
}
Войти в полноэкранный режим Выйти из полноэкранного режима

NonNullable создает новый тип, исключая undefined и null из исходного типа:

type PossibleNullishTodo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
} | null | undefined


type NotNullishTodo = NonNullable<PossibleNullishTodo>
// type NotNullishTodo = {
//   text: string;
//   type: "very urgent" | "urgent" | "not urgent";
//   daysToFinish: number;
//   isFinished: boolean;
}

Войти в полноэкранный режим Выход из полноэкранного режима

Условные типы

Условные типы предназначены для определения отношений между типами.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}

interface UrgentTodo extends Todo {
   type: "very urgent"
}

type ConditionalType = UrgentTodo extends Todo? true : false // true

Вход в полноэкранный режим Выход из полноэкранного режима

Сопоставленные типы

Сопоставленный тип создается на основе других типов и помогает избежать повторения кода. Давайте добавим readonly и к каждому свойству и сделаем его необязательным при отображении.

type Todo = {
text: string,
type: "very urgent" |"urgent" | "not urgent",
daysToFinish: number,
isFinished: boolean
}


type customType<Type> = {
 readonly [Property in keyof Type]?: Type[Property];
};

type ReadonlyPerson = customType<Todo>

//type ReadonlyPerson = {
   //readonly text?: string | undefined;
   //readonly type?: "very urgent" | "urgent" | "not urgent" | undefined;
   //readonly daysToFinish?: number | undefined;
   //readonly isFinished?: boolean | undefined;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Это все, что касается введения типов, надеюсь, вам понравилось 🙂

Оцените статью
Procodings.ru
Добавить комментарий