JavaScript Naming Conventions: Best Practices

JavaScript Naming Conventions: Best Practices

A name is the smallest unit of documentation in a program. Before anyone reads a function body, they read its name. Before they open a file, they read the variable names inside it. And a name that is vague, inconsistent, or misleading costs every future reader time — sometimes a lot of it.

JavaScript does not enforce naming conventions the way it enforces syntax. You can call a variable x, data, or temp2 and the language will not object. That freedom is exactly why conventions matter: with no enforcement, consistency is the only thing standing between a readable codebase and a maze.

This guide covers the whole subject: the difference between language rules and style conventions, the four casing styles, what to name each kind of value, the prefix patterns that make code self-documenting, the mistakes that make names actively misleading, and how to enforce a convention across a team.

In one sentence: Use camelCase for variables and functions, PascalCase for classes, SCREAMING_SNAKE_CASE for true constants, prefix booleans with is or has, and name things by what they mean rather than what they hold.

Rules vs Conventions

Two different things get called “naming rules,” and separating them makes everything else clearer.

Language rules

Enforced by the parser

A name cannot start with a digit.

A name cannot contain hyphens or spaces.

A name cannot be a reserved word.

Break one of these and the script does not run at all.

Style conventions

Agreed by people

Variables use camelCase.

Classes use PascalCase.

Booleans start with is.

Break one of these and nothing happens — except that someone later has to read it.

The rules are covered in detail in JavaScript Case Sensitivity. This guide is about the second column — the choices that make a codebase readable.

A convention is a shared decision

There is no universally correct convention. There is only a convention that a team applies consistently. The worst outcome is not choosing an unusual style — it is having three styles in one file.

Why conventions are worth the effort

🔍

Searchability

A consistent name is findable. Searching for fetchUser works when everything follows the same pattern.

🧠

Predictability

After a week in a codebase, you can guess names before you read them. That is the goal.

🐛

Fewer typos

Consistent casing means fewer mismatched names, and a typo is easier to spot.

📖

Self-documenting code

A good name removes the need for a comment. isExpired explains itself.

🤝

Easier review

Reviewers can focus on logic instead of deciphering what a name is supposed to mean.

🚀

Faster onboarding

A new developer finds things by pattern rather than by reading everything.

The Four Casing Styles

JavaScript has four conventional casing styles, and each one is tied to a specific kind of thing. Learning the mapping is most of the battle.

camelCase userName, calculateTotal

Starts lowercase, capitalizes each following word.

Used for variables, functions, and object methods.

PascalCase UserAccount, ShoppingCart

Capitalizes every word including the first.

Used for classes, constructors, and React components.

SCREAMING_SNAKE_CASE MAX_RETRIES, API_BASE_URL

All uppercase with underscores between words.

Used for true constants — values fixed before the program runs.

_leadingUnderscore _cache, _internalState

A leading underscore signals “internal — do not use from outside”.

Used for internal helpers and legacy “private” members.

What about kebab-case?

kebab-case is a valid and common convention — in CSS, in HTML class names, and in file names. In JavaScript it is a syntax error, because the hyphen is the subtraction operator.

Kebab-case in JavaScript does not work
const user-name = 'Ada'; // Parsed as: const user - name = 'Ada'; // SyntaxError: Unexpected token '-' // Valid in CSS and HTML, not in JS.
SyntaxError Use camelCase in JavaScript, and keep kebab-case for CSS class names and file names.

The full mapping

Which style to use for which kind of thing
Kind of thing Style Example
Variables camelCase userName, totalPrice
Functions camelCase calculateTotal, fetchUser
Object methods camelCase user.getName()
Classes PascalCase UserAccount, ShoppingCart
Constructor functions PascalCase function Person(name)
React components PascalCase <UserCard />
True constants SCREAMING_SNAKE_CASE MAX_RETRIES, API_URL
Internal helpers _leadingUnderscore _cache, _internalHelper
Private class fields #hash prefix this.#count
Module names camelCase or kebab-case userService.js, utils.js
CSS classes kebab-case .user-card

What to Name Each Kind of Value

Variables — a noun

A variable holds a value, so its name should be a noun that describes what the value means, not what it is.

Incorrect — vague or type-based
const data = getUser(); const str = user.name; const arr = user.posts; const temp = user.age; const x = user.email; const obj = { a: 1, b: 2 }; // Every one of these names tells // you nothing about the value.
Correct — a meaningful noun
const currentUser = getUser(); const userName = user.name; const userPosts = user.posts; const userAge = user.age; const userEmail = user.email; const options = { a: 1, b: 2 }; // Each name describes what the value // represents.

Functions — a verb

A function does something, so its name should be a verb phrase. Reading it at the call site should describe the action.

// A verb phrase describes what the function does
function calculateTotal(items) { }
function fetchUser(id) { }
function renderCard(data) { }
function validateEmail(value) { }
function formatPrice(cents) { }
function parseQueryString(search) { }
function isWithinRange(value, min, max) { }

// Nouns as function names are a smell —
// they usually mean the function is doing
// too much or the name is not specific
function user(id) { }        // what about the user?
function total(items) { }    // total what?

Classes — a noun in PascalCase

// A class describes a kind of thing
class UserAccount { }
class ShoppingCart { }
class HttpClient { }
class ValidationError extends Error { }

// Methods inside a class still use camelCase
class UserAccount {
    constructor(name) {
        this.name = name;
        this.#createdAt = new Date();
    }

    #createdAt;   // private field

    getDisplayName() { }
    updateEmail(newEmail) { }
    isActive() { }
}

Constants — SCREAMING_SNAKE_CASE, but only when it is true

This is the rule people get wrong most often. SCREAMING_SNAKE_CASE is reserved for values that are known before the program runs — configuration, limits, magic numbers. A const holding a computed value is not one of those.

Incorrect — computed values
function process(data) { const RESULT = data.map(transform); const COUNT = data.length; const AVERAGE = SUM / COUNT; // These are const, but they are // computed at runtime. SCREAMING // case is misleading. }
Correct — camelCase for computed values
function process(data) { const result = data.map(transform); const count = data.length; const average = sum / count; // Same `const` keyword, but // camelCase because the value // is computed, not fixed. }
// True constants — SCREAMING_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = 'https://api.example.com';
const DEFAULT_TIMEOUT_MS = 5000;
const TAX_RATE = 0.2;
const SUPPORTED_LOCALES = ['en', 'fr', 'de'];

// Module-level config objects often get this treatment too
const CONFIG = Object.freeze({
    retries: 3,
    timeout: 5000
});

// But a value computed from other values is camelCase,
// even at module level
const defaultTimeout = MAX_RETRIES * 1000;   // computed
The test

Ask: “could this value ever be different at runtime?” If yes, it is not a true constant — use camelCase. If it is fixed forever, use SCREAMING_SNAKE_CASE.

The Prefix Patterns That Do the Heavy Lifting

A small set of prefixes carries a surprising amount of meaning. Learning them makes names self-documenting without any extra effort.

  • Booleans that describe state. isReady, hasPermission, isLoading, hasError. The name reads as a question, which is exactly what an if statement asks.
  • Booleans that describe capability or intent. canEdit, shouldRetry, canSubmit. Useful when the boolean is about what is allowed rather than what currently is.
  • Event handlers and callbacks. handleClick is the function that does the work; onClick is the prop or option it is passed to. The distinction makes the role obvious.
  • Accessors. getUser() reads a value; setUser() writes one. In classes, get and set are also real keywords for property accessors.
  • Data retrieval. fetchUser() suggests a network request; loadConfig() suggests reading from disk or cache. The verb signals the cost.

Booleans should read as a question

// These read naturally inside an if statement
if (isLoading) { }
if (hasPermission) { }
if (canEdit) { }
if (shouldRetry) { }

// These do not — the reader has to work out
// what the boolean means
if (loading) { }
if (permission) { }
if (edit) { }
if (retry) { }

// And avoid negative names — a double negative is
// almost always harder to read
if (!isNotReady) { }    // confusing
if (isReady) { }        // clearer

// If the value is genuinely the absence of something,
// name it that way and use it that way
if (isMissing) { }      // fine — it reads as a question

Handlers vs callbacks

Ambiguous — which is which?
function click() { } button.addEventListener('click', click); // `click` collides with the event name // and reads like a noun.
Clear — handle and on
function handleClick(event) { } button.addEventListener('click', handleClick); // Or, in a component API: <Button onClick={handleClick} /> // handle = the function // on = the prop it is passed to

See the difference in real code

This example is built entirely with prefix conventions. Read the variable names and it should be clear what each one holds before you look at the code that produces it.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Prefix Conventions</title>
    <style>
        body {
            font-family: system-ui, sans-serif;
            padding: 28px;
            background: #f8fafc;
            margin: 0;
            color: #0f172a;
        }
        .panel {
            background: #fff;
            border: 1px solid #e2e8f0;
            border-radius: 14px;
            padding: 22px;
            max-width: 420px;
        }
        .status {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.82rem;
            font-weight: 700;
            letter-spacing: 0.06em;
            text-transform: uppercase;
            margin-bottom: 14px;
        }
        .dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
        }
        .dot--on { background: #16a34a; box-shadow: 0 0 8px rgba(22,163,74,.5); }
        .dot--off { background: #cbd5e1; }
        .label { color: #64748b; }
        .btn {
            border: 0;
            border-radius: 10px;
            background: #0891b2;
            color: #fff;
            font: inherit;
            font-weight: 600;
            font-size: 0.88rem;
            padding: 10px 18px;
            cursor: pointer;
            margin-right: 8px;
        }
        .btn:hover { background: #0e7490; }
        .btn:disabled { background: #cbd5e1; cursor: not-allowed; }
    </style>
</head>
<body>

    <div class="panel">
        <div class="status">
            <span class="dot dot--off" id="dot"></span>
            <span id="label">Not running</span>
        </div>
        <button class="btn" id="toggle">Start</button>
    </div>

    <script>
        // Every name below signals its role through its prefix

        let isRunning = false;               // boolean — reads as a question
        let hasStartedOnce = false;          // boolean — also a question
        const MAX_TOGGLES = 5;               // true constant
        let toggleCount = 0;                 // computed value — camelCase

        const dotElement   = document.getElementById('dot');
        const labelElement = document.getElementById('label');
        const toggleButton = document.getElementById('toggle');

        function canToggle() {               // capability — can
            return toggleCount < MAX_TOGGLES;
        }

        function renderStatus() {            // verb — does something
            dotElement.className   = isRunning ? 'dot dot--on' : 'dot dot--off';
            labelElement.textContent = isRunning ? 'Running' : 'Not running';
            toggleButton.textContent = isRunning ? 'Stop' : 'Start';
            toggleButton.disabled    = !canToggle();
        }

        function handleToggle() {            // handler — handle
            if (!canToggle()) return;

            isRunning      = !isRunning;
            hasStartedOnce = true;
            toggleCount   += 1;

            renderStatus();
        }

        toggleButton.addEventListener('click', handleToggle);
        renderStatus();
    </script>

</body>
</html>

Notice how the names alone tell you the shape of the program. isRunning and hasStartedOnce are obviously booleans. canToggle() is obviously a capability check. handleToggle is obviously an event handler. Nothing here needs a comment to explain what it holds.

How Long Should a Name Be?

The right length depends on the scope. A name used across a whole module needs to carry its meaning on its own. A name used inside a two-line loop can afford to be short.

Tiny scope → short name
→
Medium scope → descriptive
→
Module scope → fully spelled out
// Fine — the scope is two lines and the meaning is obvious
for (let i = 0; i < items.length; i++) { }

// Fine — conventional mathematical shorthand
function distance(x1, y1, x2, y2) { }

// Not fine — `u` is used across a whole module
export function u(id) { }               // what is u?

// Better
export function fetchUser(id) { }

// Fine — a short name inside a small callback
items.map(n => n * 2);

// Not fine — a short name for something important
const d = new Date();
const t = calculateTotal(cart);          // what is t?

// Better
const createdAt = new Date();
const orderTotal = calculateTotal(cart);
The proportionality rule

The length of a name should be proportional to the size of its scope. A loop index can be one character; a variable that lives in a module for its whole life should be spelled out completely.

When short names are acceptable

  • Loop indices. i, j, and k are universal.
  • Coordinates and dimensions. x, y, w, h in geometry or graphics code.
  • Array callbacks. n, item, el inside a map or forEach.
  • Error catch variables. err or e is universally understood.
  • Event variables. event or evt inside a handler.

Everywhere else, a short name costs more time to decode than it saved in typing.

Abbreviations: usually a mistake

usrPrflCrd

Shorter to type, much harder to read.

userProfileCard

Twice as long, read instantly.

btnClkHndlr

Only the author knows what this does.

handleButtonClick

Self-explanatory at every call site.

calcTtlAmt

Vowel removal is not compression.

calculateTotalAmount

Long, and worth every character.

Your editor autocompletes

The argument for short names was always typing speed. That argument stopped being true around 2010. Type three characters and press Tab — the cost is the same, and the reader gets a real name.

Naming in Practice: Before and After

The clearest way to see the value of conventions is a refactor. Here is the same component written twice. Both versions work; only one is maintainable.

Before — vague and inconsistent

// What is `d`? What is `x`? What does `f` do?
function f(d) {
    const x = d.list;
    const t = x.length;

    if (t === 0) {
        return 'no data';
    }

    let s = 0;
    for (let i = 0; i < t; i++) {
        s += x[i].p;
    }

    return s;
}

const d = getData();
const r = f(d);
console.log(r);

// Inconsistent casing in the same file
const user_name = 'Ada';
const UserEmail = 'ada@example.com';
const MAX_ITEM_COUNT = 10;
const default_count = 5;

After — descriptive and consistent

// Every name says what it holds
function calculateOrderTotal(order) {
    const lineItems = order.lineItems;
    const itemCount = lineItems.length;

    if (itemCount === 0) {
        return 0;
    }

    let total = 0;
    for (let i = 0; i < itemCount; i++) {
        total += lineItems[i].price;
    }

    return total;
}

const currentOrder = fetchOrder();
const orderTotal = calculateOrderTotal(currentOrder);
console.log(orderTotal);

// Consistent casing throughout
const userName = 'Ada';
const userEmail = 'ada@example.com';
const MAX_ITEM_COUNT = 10;      // true constant
const defaultItemCount = 5;     // computed value
What changed in the refactor
Before After Why
f calculateOrderTotal The function name describes the action
d order The parameter name describes the value
x lineItems Reads as a noun in the code below it
t itemCount The count has a real name
s total The accumulator is self-describing
'no data' 0 Returning a number consistently is better than a string sentinel
user_name userName One casing style instead of three
default_count defaultItemCount Not a true constant, so camelCase

Common Naming Mistakes

Each of these makes a name actively harder to work with. They are the ones that come up most often in real code reviews.

1. Single letters outside a tiny scope

Incorrect — meaningless
function p(u) { const r = u.n + ' ' + u.l; const e = u.m.toLowerCase(); return { r, e }; } // What is p? What is u? What is r? // The reader has to open the // implementation to find out.
Correct — descriptive
function formatUserProfile(user) { const displayName = user.firstName + ' ' + user.lastName; const normalizedEmail = user.email.toLowerCase(); return { displayName, normalizedEmail }; }

2. Names that repeat the type

Incorrect — Hungarian notation
const strName = 'Ada'; const arrItems = [1, 2, 3]; const objConfig = { a: 1 }; const numCount = 5; const boolIsReady = true; // The type is already visible in // the value. The prefix adds nothing.
Correct — meaning instead
const userName = 'Ada'; const lineItems = [1, 2, 3]; const config = { a: 1 }; const itemCount = 5; const isReady = true; // `userName` conveys "string" // through meaning, not a prefix.

3. Catch-all names: data, info, temp

Incorrect — could be anything
function process(data) { const info = data.info; const temp = info.value; const result = temp * 2; return result; } // Every name here is a placeholder.
Correct — specific
function doubleDiscount(product) { const discountInfo = product.discount; const discountPercent = discountInfo.value; const doubledDiscount = discountPercent * 2; return doubledDiscount; }

4. Negative boolean names

Incorrect — double negative
const isNotReady = true; if (!isNotReady) { // "if not not ready" — the reader // has to work out what this means } const dontShow = false; if (!dontShow) { }
Correct — positive naming
const isReady = false; if (isReady) { // reads naturally } const shouldShow = true; if (shouldShow) { }

5. Inconsistent casing in the same file

Incorrect — four styles at once
const user_name = 'Ada'; const userEmail = 'x@y.com'; const UserAge = 36; const USER_CITY = 'London'; const user-country = 'UK'; // Which convention is this file // following? None of them.
Correct — one style
const userName = 'Ada'; const userEmail = 'x@y.com'; const userAge = 36; const userCity = 'London'; const userCountry = 'UK';

6. Names that lie

Incorrect — the name is wrong
// Returns an array, named as a boolean function isValid() { return [true, false, true]; } // Named as a count, holds a string const itemCount = 'many'; // Named as a getter, mutates state function getUser() { currentUser = fetchUser(); return currentUser; }
Correct — the name matches
function getValidationResults() { return [true, false, true]; } const itemCountLabel = 'many'; function loadUser() { currentUser = fetchUser(); return currentUser; }

7. Names that differ by one character

Incorrect — hard to tell apart
const userList = []; const usersList = []; const listOfUsers = []; // Three names for what is probably // the same thing, or three things // nobody can distinguish.
Correct — each name is distinct
const activeUsers = []; const archivedUsers = []; const invitedUsers = []; // The name says which set of users // this is, not just that it is a list.

8. Abbreviating past the point of clarity

Incorrect — unreadable
function calcTtl(itms) { const sbttl = itms.reduce((s, i) => s + i.p, 0); const tx = sbttl * 0.2; return { sbttl, tx }; }
Correct — readable
function calculateTotal(items) { const subtotal = items.reduce((sum, item) => sum + item.price, 0); const tax = subtotal * 0.2; return { subtotal, tax }; }

9. Shadowing a built-in

Incorrect — shadows a global
function process(list) { const Array = list.slice(); // `Array` now refers to a local // variable. Any later use of the // built-in Array inside this // function breaks. }
Correct — a distinct name
function process(list) { const items = list.slice(); // No collision with the built-in. }

10. Naming by position rather than role

Incorrect — breaks on mobile
const leftColumn = getSidebar(); const rightColumn = getMainContent(); const topBar = getHeader(); // On a phone, the sidebar often // moves above the content. Now the // names are factually wrong.
Correct — names the role
const sidebar = getSidebar(); const mainContent = getMainContent(); const siteHeader = getHeader(); // Where it sits can change. // What it is does not.
A misleading name is worse than a vague one

A name like data makes you read the code. A name like itemCount that actually holds a string makes you trust something false. When you change what a value holds, rename it.

Making It Stick: Tooling and Consistency

A convention that lives only in a document drifts. A convention enforced by a tool holds. The good news is that the tooling is easy to set up.

ESLint

// .eslintrc.json — enforce the common conventions

{
    "rules": {
        // Variables and functions must be camelCase
        "camelcase": ["error", { "properties": "always" }],

        // No shadowing built-ins or outer variables
        "no-shadow": "error",
        "no-shadow-restricted-names": "error",

        // No redeclaring — catches accidental duplicates
        "no-redeclare": "error",

        // Custom pattern rules for specific naming families
        "id-match": ["error", "^[a-z][a-zA-Z0-9]*$", {
            "properties": false,
            "onlyDeclarations": true
        }]
    }
}

TypeScript’s naming-convention rule

If you use TypeScript with the ESLint plugin, the @typescript-eslint/naming-convention rule lets you express the whole table in one place.

// eslint.config.js — the full convention as a rule

'@typescript-eslint/naming-convention': [
    'error',

    // Variables — camelCase, or SCREAMING_SNAKE_CASE for constants
    {
        selector: 'variable',
        format: ['camelCase', 'UPPER_CASE']
    },

    // Booleans must start with a recognised prefix
    {
        selector: 'variable',
        types: ['boolean'],
        format: ['camelCase'],
        prefix: ['is', 'has', 'can', 'should', 'did']
    },

    // Functions — camelCase
    {
        selector: 'function',
        format: ['camelCase']
    },

    // Classes, interfaces, and type aliases — PascalCase
    {
        selector: 'typeLike',
        format: ['PascalCase']
    },

    // Object properties may also be snake_case, for API payloads
    {
        selector: 'objectLiteralProperty',
        format: ['camelCase', 'snake_case']
    }
]

Prettier does not do this — and that is fine

Prettier formats whitespace, quotes, and line breaks. It does not rename anything, and it cannot enforce a casing convention. That is what ESLint is for. The two work together: Prettier handles layout, ESLint handles rules.

What each tool is responsible for
Concern Prettier ESLint
Indentation and line length Yes No
Quote style Yes Partly
Semicolons Yes Partly
Naming conventions No Yes
Unused variables No Yes
Shadowed variables No Yes
Possible bugs No Yes
Run it in CI

A linter that only runs when someone remembers is a linter that does not run. Add eslint . to the CI pipeline so a naming violation blocks the build rather than appearing in a review comment.

Best Practices

These habits cover nearly every naming decision you will face. When in doubt, start here.

🐪

camelCase for variables and functions

The default for everything that is not a class or a true constant.

🏛️

PascalCase for classes

Classes, constructors, and React components all start with a capital letter.

📢

SCREAMING_SNAKE_CASE for true constants

Only for values fixed before the program runs. Computed values use camelCase.

❓

Prefix booleans

is, has, can, should — they read as a question.

🎯

Verbs for functions, nouns for variables

fetchUser does something; currentUser holds something.

📏

Match length to scope

Short names in tiny scopes, fully spelled out everywhere else.

🚫

Avoid abbreviations

Autocomplete makes long names cost nothing. Use the readable version.

🎭

Name by role, not position

sidebar, not leftColumn. Layouts change; roles do not.

🤝

Enforce it with a linter

A convention that is checked in CI is a convention that survives.

The one-line summary

Say what a thing means, match the length to the scope, use the right casing for the right kind of value, and let ESLint keep everyone honest.

Frequently Asked Questions

1. What are JavaScript naming conventions?

Naming conventions are agreed-upon rules for choosing and formatting names in code. They cover which casing style to use for each kind of value, how long a name should be, and which prefix patterns signal a boolean, a handler, or an internal value. They are not enforced by the language itself.

2. What casing style should I use in JavaScript?

camelCase for variables and functions, PascalCase for classes and constructors, SCREAMING_SNAKE_CASE for true constants, and a leading underscore for anything internal. Hyphens are not valid in JavaScript identifiers because they mean subtraction.

3. Why do JavaScript naming conventions matter?

Code is read far more often than it is written. Consistent names make a codebase searchable, reduce the chance of typo bugs, and let any developer predict what a function or variable does before reading its implementation.

4. Are naming conventions the same as the language rules?

No. The language rules determine whether a name is legal and are enforced by the parser — a name cannot start with a digit or be a reserved word. Naming conventions are a style choice and are not enforced by the language, though a linter can enforce them.

5. How long should a variable name be?

Long enough to be unambiguous and short enough to read. Two or three words usually covers it. The length should be proportional to the scope: a loop counter inside a two-line loop can be i, but a value used across a whole module needs a descriptive name.

6. Should I use short names like a, b, or x?

Only in very small scopes where the meaning is obvious — a loop index, or a mathematical coordinate. In any other context a short name costs more time to decode than it saves in typing, and it becomes a genuine problem when the code is read later.

7. How should I name boolean variables?

Prefix booleans so they read as a question: isReady, hasPermission, canEdit, shouldRetry. This makes the condition in an if statement read naturally, and it prevents the common mistake of writing a negative boolean name such as isNotReady.

8. How should I name event handlers?

The usual convention is a handle prefix for the function that does the work, such as handleClick or handleSubmit, and an on prefix for the prop or callback it is passed to, such as onClick. This makes the difference between a handler and a callback obvious.

9. Should I include the type in a variable name?

No. A name like strName or arrItems is called Hungarian notation and it duplicates information the value already carries. If the type matters, a name like userName or lineItems conveys it through meaning instead, and TypeScript can enforce it properly.

10. How do I name a constant?

Use SCREAMING_SNAKE_CASE only for values known before the program runs — configuration, limits, and magic numbers, such as MAX_RETRIES or API_BASE_URL. A const declared inside a function that holds a computed value is not a true constant and should use camelCase.

11. What does a leading underscore mean in JavaScript?

It is a convention signalling that a name is internal and should not be used from outside. It is not enforced by the language. For genuinely private class members, use the hash prefix, which the language does enforce.

12. Can a linter enforce naming conventions?

Yes. ESLint includes rules such as camelcase and id-match, and @typescript-eslint/naming-convention for TypeScript. A linter turns a convention from a suggestion into a check, which is the most reliable way to keep a codebase consistent across contributors.

Key Takeaways

  • Naming conventions are style, not syntax — the language does not enforce them.
  • camelCase for variables and functions, PascalCase for classes, SCREAMING_SNAKE_CASE for true constants.
  • Hyphens are not valid in JavaScript identifiers — use camelCase instead.
  • Prefix booleans with is, has, can, or should.
  • Use verbs for functions and nouns for variables.
  • Match the length of a name to the size of its scope.
  • Use handle for the handler function and on for the prop it is passed to.
  • Avoid Hungarian notation — the type is already in the value.
  • Avoid catch-all names like data, info, and temp.
  • A name that lies is worse than a name that is vague — rename when the value changes.
  • Name by role, not by position — layouts change, roles do not.
  • Enforce the convention with ESLint in CI so it survives past the first week.

What to Learn Next

Now that the naming conventions are clear, the next step is the language rules that sit underneath them. Read JavaScript Case Sensitivity for what the parser actually enforces, and JavaScript Strict Mode for the mode that catches several naming mistakes automatically.

From there, explore JavaScript Syntax Explained, JavaScript Statements and Expressions, and JavaScript Functions Explained. For the CSS side of the same subject, read CSS Naming Conventions.

If you are still connecting the pieces, read What Is JavaScript?, JavaScript Comments, and JavaScript vs TypeScript for the surrounding context.

Practice Challenge

The fastest way to internalize a convention is to apply it to code that was written badly. This exercise takes about twenty-five minutes.

  1. Create index.html and app.js, and load the script with <script src="app.js" defer></script>.
  2. Write a deliberately badly named function: short name, single-letter parameters, and a body full of data, temp, and x. Confirm it works.
  3. Add a second function that returns a boolean but is named as a noun, such as status().
  4. Add four variables in the same file using four different casing styles: user_name, userEmail, UserAge, and USER_CITY.
  5. Add a const inside a function that holds a computed value and name it in SCREAMING_SNAKE_CASE.
  6. Now refactor every name: rename the function to a verb phrase, its parameters to descriptive nouns, and the internal variables to meaningful names.
  7. Rename the boolean function to start with is, has, or can.
  8. Convert all four variables to camelCase, and change the computed constant to camelCase as well.
  9. Add a genuine constant at the top of the file with SCREAMING_SNAKE_CASE — something like MAX_ITEMS.
  10. Add an event listener and name the handler with a handle prefix.
  11. Now install ESLint in the project and enable the camelcase, no-shadow, and no-redeclare rules. Run it and see whether your refactored file passes.
  12. Finally, deliberately rename one variable to differ from its use site by a single capital letter. Run ESLint and confirm it catches the undeclared reference.

If you complete those steps, you have written code that violates every major convention, refactored it into something readable, added a genuine constant alongside a computed one, and configured a linter to keep the rules in place. That sequence — write badly, refactor, enforce — is the whole practice of naming conventions. The refactor is the part that teaches you what the rules are for.

Inar Learn
Inar Learnhttps://inarlearn.com
Inar Learn is an innovative online learning platform offering high-quality courses, tutorials, and resources to help learners gain practical skills and grow their knowledge.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here