TypeScript литералы: как применять строковые методы

Короткий ответ: строковые методы применяются не к типам, а к значениям. В TypeScript есть строковые значения, например "hello", и есть строковые literal types, например type Status = "draft" | "published". Метод toUpperCase() можно вызвать у значения, но нельзя "вызвать метод у типа", потому что тип существует только во время проверки кода

Пример значения:

const title = "typescript";
console.log(title.toUpperCase());

Пример literal type:

type Status = "draft" | "published";

Status нужен для ограничения допустимых строк, а не для выполнения строковых операций

Строковый литерал как значение

const role = "admin";

console.log(role.toUpperCase());
console.log(role.includes("ad"));

Здесь role — обычная строка со строковыми методами JavaScript. TypeScript просто знает, что значение равно "admin"

Если объявить через let, тип станет шире:

let role = "admin";

Теперь TypeScript обычно понимает role как string, потому что значение можно поменять

Literal type как ограничение

type Role = "admin" | "editor" | "user";

function setRole(role: Role) {
  console.log(role);
}

setRole("admin");

А вот так нельзя:

setRole("manager");

Потому что "manager" не входит в Role

Как применить строковый метод и сохранить тип

Допустим, нужно нормализовать ввод:

type Role = "admin" | "editor" | "user";

function parseRole(input: string): Role | null {
  const value = input.trim().toLowerCase();

  if (value === "admin" || value === "editor" || value === "user") {
    return value;
  }

  return null;
}

Методы trim() и toLowerCase() применяются к input, то есть к строковому значению. Потом TypeScript сужает тип через проверки value === "admin" и разрешает вернуть Role

as const

Если есть список допустимых значений:

const roles = ["admin", "editor", "user"] as const;

type Role = typeof roles[number];

Теперь Role автоматически равен "admin" | "editor" | "user"

Можно сделать проверку:

function isRole(value: string): value is Role {
  return (roles as readonly string[]).includes(value);
}

И использовать:

function parseRole(input: string): Role | null {
  const value = input.trim().toLowerCase();
  return isRole(value) ? value : null;
}

Template literal types

TypeScript умеет строить типы строк по шаблону:

type EventName = `user:${"created" | "deleted"}`;

const event: EventName = "user:created";

Такой тип полезен для событий, ключей переводов, CSS-токенов и API-имен. Но это снова тип, а не runtime-строка

Частые ошибки

Первая ошибка — пытаться вызвать метод у типа:

type Name = "dinar";
// Name.toUpperCase() - так нельзя

Вторая ошибка — после toLowerCase() ожидать автоматический literal type. Метод возвращает string, поэтому нужна проверка

Третья ошибка — использовать as Role без проверки. Это может скрыть неправильное значение

Четвертая ошибка — путать String и string

Пятая ошибка — держать допустимые значения отдельно от типа и забывать обновлять одно из двух. as const помогает связать список и тип

Самопроверка

Создайте массив statuses = ["new", "paid", "cancelled"] as const, выведите из него тип Status, затем напишите parseStatus(input: string): Status | null. Внутри используйте trim() и toLowerCase(), но возвращайте статус только после проверки

Что почитать дальше по TypeScript

Если нужен общий маршрут по теме, откройте рубрику TypeScript. Для соседних задач пригодятся эти разборы:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x