Опубліковано: 2026-05-13
camelCase vs snake_case: коли що обрати (з прикладами)
camelCase чи snake_case? Залежить від мови, шару й угоди команди. Повний розбір: правила мов, пастки в JSON API і конвертер регістру онлайн.

Відповідь дається секунд за 30, а інтерналізувати її повністю — справа всієї кар'єри: бери те, що вже вирішила спільнота мови. camelCase у JavaScript. snake_case у Python. Готово.
Але справжня складність — на межах: JSON API, схеми баз даних, конфіги і кросмовні проєкти, де стикаються дві спільноти. Саме там починається безлад — і саме про це ця стаття.
Коротка довідка: яка конвенція куди
Перш ніж занурюватися в «чому», ось остаточна таблиця-шпаргалка:
| Контекст | Конвенція | Приклад |
|---|---|---|
| Змінні / функції в JavaScript | camelCase | wordCount, parseText() |
| Класи в JavaScript | PascalCase | TextAnalyzer, WordCounter |
| Константи в JavaScript | UPPER_SNAKE_CASE | MAX_WORDS, DEFAULT_WPM |
| Інтерфейси / типи в TypeScript | PascalCase | TextStats, AnalysisResult |
| Назви файлів TypeScript / Vue | kebab-case | word-counter.ts, text-analyzer.vue |
| Змінні / функції в Python | snake_case | word_count, parse_text() |
| Класи в Python | PascalCase | TextAnalyzer, WordCounter |
| Константи в Python | UPPER_SNAKE_CASE | MAX_WORDS, DEFAULT_WPM |
| Ruby / Rails | snake_case | word_count, parse_text |
| Go | camelCase / PascalCase | wordCount (неекспортований), WordCount (експортований) |
| Публічні методи Java / Kotlin | camelCase | getWordCount(), parseText() |
| Назви колонок у SQL | snake_case | word_count, created_at |
| Назви CSS-класів | kebab-case | word-counter, text-toolbar |
| URL-слаги | kebab-case | /case-converter, /remove-spaces |
| Назви npm-пакетів | kebab-case | nuxt-gtag, vue-router |
| Ключі JSON у REST API | camelCase (JS-first) або snake_case (Python-first) | wordCount / word_count |
| Змінні середовища | UPPER_SNAKE_CASE | NODE_ENV, API_SECRET |
Збережи цю таблицю в закладки. Вона покриває 95% рішень, які ти ухвалюватимеш на проєкті.
camelCase: вибір JavaScript і Java
camelCase склеює слова, пишучи з великої літери перше слово після першого: wordCount, parseText, maxRetries.
Де це закон:
- Змінні, функції і властивості об'єктів у JavaScript та TypeScript
- Методи екземплярів і змінні в Java
- Методи в Objective-C
- Ключі JSON, які споживають JavaScript-фронтенди (за угодою, не за специфікацією)
- Неекспортовані ідентифікатори в Go (
wordCount) та експортовані через PascalCase (WordCount)
Походження camelCase у JavaScript веде безпосередньо до Java. Брендан Айк спроєктував синтаксис JavaScript так, щоб він подобався Java-розробникам у 1995-му, і вбудовані API JavaScript пішли за угодою Java: getElementById, addEventListener, hasOwnProperty. П'ятнадцять років браузерних API навчили ціле покоління друкувати camelCase інстинктивно.
Варіант PascalCase (UpperCamelCase) пише з великої кожне слово, включно з першим: TextAnalyzer, HttpRequest, WordCounter. У JavaScript PascalCase сигналізує «це конструктор або клас». У C# і Java його використовують для всіх публічних методів — пастка, коли ти вперше читаєш сорси .NET, прийшовши зі світу JS.
snake_case: вибір Python і баз даних
snake_case пише все з малої й розділяє слова підкресленнями: word_count, parse_text, max_retries.
Де це закон:
- Змінні, функції і назви модулів у Python (PEP 8 — без варіантів у будь-якому серйозному Python-проєкті)
- Методи і змінні в Ruby та Rails
- Назви колонок у PostgreSQL і MySQL (нав'язано угодою, не рушієм БД)
- Змінні і функції в Rust
- Функції стандартної бібліотеки C (
printf,strlen— технічно без роздільника, але це окремі слова) - Назви змінних середовища у варіанті UPPER_SNAKE_CASE
Чому Python обрав snake_case: Гвідо ван Россум написав PEP 8 у 2001-му, щоб описати стиль, який уже використовувала стандартна бібліотека Python. Бібліотека з'явилася раніше за PEP 8 і використовувала snake_case, бо Unix-утиліти і C уже встановили цей патерн для багатослівних ідентифікаторів. Python просто закодифікував наявну практику.
Пастка PostgreSQL з колонками в camelCase: SQL за специфікацією нечутливий до регістру, а PostgreSQL зводить кожен незакавичений ідентифікатор до нижнього регістру на етапі парсингу. Якщо ти створиш колонку з назвою wordCount, Postgres збереже її як wordcount. Твій запит SELECT wordCount FROM ... тихо працює — поки якийсь джун не напише SELECT "wordCount" FROM ... з лапками, не отримає помилку column "wordCount" does not exist і не згаює годину на дебаг. Виправлення — завжди ставити лапки, а це означає, що тобі доведеться ставити їх усюди і назавжди. У word_count такої пастки немає — він переживає зведення регістру цілим. Бери snake_case і збережи собі нерви на суперечках про дрібниці. snake_case ще й узгоджується з тим, як ORM на кшталт SQLAlchemy, Prisma та ActiveRecord за замовчуванням генерують назви колонок у міграціях.
Проблема межі API
Саме тут більшість команд припускається помилок.
Python-бекенд (snake_case), що обслуговує JavaScript-фронтенд (camelCase), створює дилему: чия конвенція перемагає на рівні API?
Варіант 1: snake_case усюди
Бекенд повертає { "word_count": 432 }. Фронтенд звертається до response.word_count. Це працює, але в JavaScript почувається неправильно — властивості, що виглядають як Python. Якщо ти на TypeScript, твої інтерфейси тепер мають ключі в snake_case, що виділяється на тлі кожної угоди JavaScript.
Варіант 2: camelCase усюди
Бекенд серіалізує в { "wordCount": 432 }. FastAPI робить це автоматично через alias_generator. Django REST Framework підтримує це через кастомний рендерер. Фронтенд отримує ключі, що виглядають рідними.
Варіант 3: обери стандарт і тримайся його Специфікація JSON:API використовує camelCase. Рекомендації OpenAPI віддають перевагу camelCase. GraphQL (схема і запити) за угодою — строго camelCase. Якщо ти будуєш публічний API, більшість генераторів SDK очікують саме camelCase.
Найгірший варіант: змішувати їх. { "wordCount": 432, "created_at": "2026-05-13" } — ось що стається, коли двоє людей написали серіалізатор, не поговоривши між собою. Нормалізуй на рівні серіалізатора, а не клієнта.
Ось як ці три варіанти виглядають на практиці:
┌─────────────────────────────────────────────────────────────┐
│ API BOUNDARY OPTIONS │
├───────────────┬─────────────────┬───────────────────────────┤
│ Option │ API Response │ Frontend access │
├───────────────┼─────────────────┼───────────────────────────┤
│ snake_case │ word_count: 432 │ response.word_count │
│ camelCase │ wordCount: 432 │ response.wordCount ✓ │
│ Mixed (avoid) │ wordCount: 432, │ response.wordCount + │
│ │ created_at: … │ response.created_at ✗ │
└───────────────┴─────────────────┴───────────────────────────┘
Конвертація між конвенціями
Рано чи пізно тобі доведеться конвертувати — рефакторячи кодову базу, адаптуючи відповідь стороннього API чи мігруючи схему БД.
Підхід через регулярку — найнадійніший спосіб програмно конвертувати camelCase у snake_case:
// camelCase → snake_case
const toSnakeCase = (str) =>
str.replace(/([a-z])([A-Z])/gu, '$1_$2').toLowerCase()
// snake_case → camelCase
const toCamelCase = (str) =>
str.replace(/_([a-z])/gu, (_, c) => c.toUpperCase())
Ключовий патерн — ([a-z])([A-Z]): він знаходить кожен перехід від малої літери до великої, а це і є межа camelCase. Зверни увагу на прапорець u: хоча саме цей патерн працює лише з ASCII-літерами, звичку ставити u варто виробити для будь-якого патерну, що працює з Unicode-текстом.
VS Code, крок за кроком (без плагінів):
- Відкрий Find & Replace:
Ctrl+H(Windows/Linux) або⌘+H(Mac) - Натисни іконку
.*, щоб увімкнути режим regex - Знайти:
([a-z])([A-Z]) - Замінити:
$1_$2 - Тисни Replace All — це вставить підкреслення на кожній межі camelCase
- Відкрий термінал і прожени файл через переведення в нижній регістр, або зроби другий прохід Find All →
[A-Z]→ у нижній регістр вручну
$1 і $2 в рядку заміни посилаються на дві групи захоплення в патерні — $1 це мала літера перед межею, $2 це велика літера після неї. Багато розробників не знають, що regex-заміна у VS Code підтримує зворотні посилання на групи захоплення з коробки, без жодних розширень.
Для разових конвертацій встав свій ідентифікатор у наш інструмент Зміна регістру — він працює на 100% у твоєму браузері, на сервер не йде жоден байт — і обери формат виводу з випадайки.
Для масового перейменування по документу чи вставленому блоку коду скористайся Пошуком і заміною з регуляркою ([a-z])([A-Z]) → $1_$2, щоб конвертувати camelCase у snake_case, а потім зроби другий прохід для переведення в нижній регістр. Інструмент підтримує повноцінні регулярні вирази з підстановкою груп захоплення і показує живий лічильник збігів, перш ніж ти застосуєш зміни.
Якщо цікаво, як підхід із регуляркою порівнюється з іншими патернами обробки тексту, гайд із пошуку й заміни за регулярними виразами детально розбирає групи захоплення, квантифікатори і випереджальні перевірки.
Крайові випадки, на яких усі спотикаються
Абревіатури в camelCase: має бути parseHTML чи parseHtml? getURL чи getUrl? Гайд зі стилю Java від Google каже трактувати абревіатури як слова: parseHtml, getUrl. Гайд Microsoft для C# каже лишати їх у верхньому регістрі, якщо вони 2 символи: GetIO, але GetUrl. У JavaScript універсального правила немає. Обери одне і задокументуй — реальна проблема саме в неузгодженості всередині кодової бази.
Числа в ідентифікаторах: base64Encode чи base_64_encode? Конвенція — трактувати числа як символи слова в нижньому регістрі: base64Encode, to_utf8. Одні команди пишуть toUtf8, інші toUTF8 — і знову, гайд зі стилю важливіший за окремий вибір.
Підкреслення на початку: _privateMethod — це угода JavaScript (не нав'язана мовою), щоб сигналізувати «не викликай це ззовні модуля». Python використовує одне підкреслення на початку (_private) так само, а подвійне (__mangled) запускає name mangling у класах. У сучасному JavaScript із синтаксисом #privateField угода з підкресленням здебільшого застаріла, але ти все ще побачиш її в старіших кодових базах.
Первинні ключі в базах даних: більшість фреймворків очікують id, а не Id чи ID. Зовнішні ключі йдуть за патерном user_id, post_id — snake_case із суфіксом _id. Тримай це послідовно, інакше твій ORM генеруватиме запити, що не збігаються зі схемою.
Кілька слів про примус інструментами
Найважливіша властивість конвенції іменування — те, що про неї не треба думати. Якщо твоя команда сперечається про регістр на код-рев'ю, ви витрачаєте розумову енергію не на те.
ESLint має правила camelcase і @typescript-eslint/naming-convention, що нав'язують регістр на рівні лінтера. Black (форматер Python) не перейменовує змінні, але pylint і flake8 з плагінами PEP 8 підсвітять порушення snake_case. Налаштуй правило лінтера один раз, нав'яжи на CI — і розмова закінчена.
Для разової роботи з текстом — відповіді API, конфіги, скрипти міграцій — інструмент Зміна регістру обробляє всі поширені формати, включно з camelCase, snake_case, PascalCase, kebab-case та UPPER_SNAKE_CASE, одним кліком.
А якщо ти колись вставляв блок тексту з неузгодженим регістром і його треба було нормалізувати — підхід зі статті як прибрати зайві пробіли в тексті онлайн працює і тут: спершу почисти текст, потім трансформуй.
Коротка відповідь
- JavaScript / TypeScript: camelCase для змінних і функцій, PascalCase для класів
- Python: snake_case для змінних і функцій, PascalCase для класів, PEP 8 не опційний
- SQL / бази даних: snake_case, завжди
- CSS / URL / npm: kebab-case
- Змінні середовища: UPPER_SNAKE_CASE
- JSON API: camelCase якщо JS-first, snake_case якщо Python-first — обери одне і серіалізуй послідовно
Коли працюєш через кілька шарів і треба швидко конвертувати, інструмент Зміна регістру обробляє всі формати, не виходячи з браузера.
