Короткий ответ: строковые методы применяются не к типам, а к значениям. В 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. Для соседних задач пригодятся эти разборы:
- 10 вопросов по TypeScript и ответы на них
- Any, unknown, never и strict
- App.tsx: что это за файл и как добавить TypeScript в React
- Conditional types в TypeScript: как работает extends



