useNamingConvention
Summary
Section titled “Summary”- Rule available since: v1.0.0
- Diagnostic Category: lint/style/useNamingConvention
- This rule has a safe fix.
- The default severity of this rule is information.
- Sources:
- Inspired from @typescript-eslint/naming-convention
 
- Inspired from 
How to configure
Section titled “How to configure”{  "linter": {    "rules": {      "style": {        "useNamingConvention": "error"      }    }  }}Description
Section titled “Description”Enforce naming conventions for everything across a codebase.
Enforcing naming conventions helps to keep the codebase consistent, and reduces overhead when thinking about the name case of a variable.
The following section describes the default conventions enforced by the rule. You can also enforce custom conventions with the rule options.
Naming conventions
Section titled “Naming conventions”All names can be prefixed and suffixed with underscores _ and dollar signs $.
Unused variables with a name prefixed with _ are completely ignored.
This avoids conflicts with the noUnusedVariables rule.
Variable and parameter names
Section titled “Variable and parameter names”All variables and function parameters are in camelCase or PascalCase.
Catch parameters are in camelCase.
Additionally, global variables declared as const or var may be in CONSTANT_CASE.
Global variables are declared at module or script level.
Variables declared in a TypeScript namespace are also considered global.
function f(param, _unusedParam) {    let localValue = 0;    try {        /* ... */    } catch (customError) {        /* ... */    }}
export const A_CONSTANT = 5;
let aVariable = 0;
export namespace ns {    export const ANOTHER_CONSTANT = "";}Examples of incorrect names:
let a_value = 0;code-block.js:1:5 lint/style/useNamingConvention  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This let name should be in camelCase or PascalCase.
  
  > 1 │ let a_value = 0;
      │     ^^^^^^^
    2 │ 
  
  ℹ Safe fix: Rename this symbol in camelCase.
  
    1   │ - let·a_value·=·0;
      1 │ + let·aValue·=·0;
    2 2 │   
  
const fooYPosition = 0;code-block.js:1:7 lint/style/useNamingConvention ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ Two consecutive uppercase characters are not allowed in camelCase because strictCase is set to true.
  
  > 1 │ const fooYPosition = 0;
      │       ^^^^^^^^^^^^
    2 │ 
  
  ℹ If you want to use consecutive uppercase characters in camelCase, then set the strictCase option to false.
    See the rule options for more details.
  
function f(FIRST_PARAM) {}code-block.js:1:12 lint/style/useNamingConvention  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This function parameter name should be in camelCase or PascalCase.
  
  > 1 │ function f(FIRST_PARAM) {}
      │            ^^^^^^^^^^^
    2 │ 
  
  ℹ Safe fix: Rename this symbol in PascalCase.
  
    1   │ - function·f(FIRST_PARAM)·{}
      1 │ + function·f(FirstParam)·{}
    2 2 │   
  
Function names
Section titled “Function names”- A functionname is incamelCaseorPascalCase.
- A global functioncan also be inUPPERCASE. This allows supporting the frameworks that require some function to use valid HTTP method names.
function trimString(s) { /*...*/ }
function Component() {    return <div></div>;}
export function GET() { /*...*/ }TypeScript enum names
Section titled “TypeScript enum names”A TypeScript enum name is in PascalCase.
enum members are by default in PascalCase.
However, you can configure the case of enum members.
See options for more details.
enum Status {    Open,    Close,}Classes
Section titled “Classes”- 
A class name is in PascalCase.
- 
Static property and static getter names are in camelCaseorCONSTANT_CASE.
- 
Class property and method names are in camelCase.
class Person {    static MAX_FRIEND_COUNT = 256;
    static get SPECIAL_PERSON_INSTANCE() { /*...*/ }
    initializedProperty = 0;
    specialMethod() {}}TypeScript type aliases and interface
Section titled “TypeScript type aliases and interface”- 
A typealias or an interface name are inPascalCase.
- 
Member names of a type are in camelCase.
- 
readonlyproperty and getter names can also be inCONSTANT_CASE.
type Named = {    readonly fullName: string;
    specialMethod(): void;};
interface Named {    readonly fullName: string;
    specialMethod(): void;}
interface PersonConstructor {    readonly MAX_FRIEND_COUNT: number;
    get SPECIAL_PERSON_INSTANCE(): Person;
    new(): Person;}Examples of an incorrect type alias:
type person = { fullName: string };code-block.ts:1:6 lint/style/useNamingConvention  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This type alias name should be in PascalCase.
  
  > 1 │ type person = { fullName: string };
      │      ^^^^^^
    2 │ 
  
  ℹ Safe fix: Rename this symbol in PascalCase.
  
    1   │ - type·person·=·{·fullName:·string·};
      1 │ + type·Person·=·{·fullName:·string·};
    2 2 │   
  
Literal object member names
Section titled “Literal object member names”- Literal object members are in camelCase.
const alice = {    fullName: "Alice",}Example of an incorrect name:
const alice = {    full_name: "Alice",}code-block.js:2:5 lint/style/useNamingConvention ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This object property name should be in camelCase.
  
    1 │ const alice = {
  > 2 │     full_name: “Alice”,
      │     ^^^^^^^^^
    3 │ }
    4 │ 
  
Import and export aliases and namespaces
Section titled “Import and export aliases and namespaces”Import and export namespaces are in camelCase or PascalCase.
import * as myLib from "my-lib";import * as Framework from "framework";
export * as myLib from "my-lib";export * as Framework from "framework";import and export aliases are in camelCase, PascalCase, or CONSTANT_CASE:
import assert, {    deepStrictEqual as deepEqual,    AssertionError as AssertError} from "node:assert";Examples of an incorrect name:
import * as MY_LIB from "my-lib";code-block.ts:1:13 lint/style/useNamingConvention  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This import namespace name should be in camelCase or PascalCase.
  
  > 1 │ import * as MY_LIB from “my-lib”;
      │             ^^^^^^
    2 │ 
  
  ℹ Safe fix: Rename this symbol in PascalCase.
  
    1   │ - import·*·as·MY_LIB·from·“my-lib”;
      1 │ + import·*·as·MyLib·from·“my-lib”;
    2 2 │   
  
TypeScript type parameter names
Section titled “TypeScript type parameter names”A TypeScript type parameter name is in PascalCase.
function id<Val>(value: Val): Val { /* ... */}TypeScript namespace names
Section titled “TypeScript namespace names”A TypeScript namespace name is in camelCase or in PascalCase.
namespace mathExtra {    /*...*/}
namespace MathExtra {    /*...*/}Ignored declarations
Section titled “Ignored declarations”Note that some declarations are always ignored. You cannot apply a convention to them. This is the case for:
- Member names that are not identifiers
class C {  ["not an identifier"]() {}}- Named imports
 import { an_IMPORT } from "mod"- Destructured object properties
const { destructed_PROP } = obj;- Class members marked with override:
class C extends B {  override overridden_METHOD() {}}- Declarations inside an external TypeScript module
declare module "myExternalModule" {  export interface my_INTERFACE {}}- Declarations inside a global declaration
declare global {  interface HTMLElement {}}Options
Section titled “Options”The rule provides several options that are detailed in the following subsections.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "strictCase": false,            "requireAscii": false,            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)",                "formats": [                  "camelCase"                ]              }            ]          }        }      }    }  }}strictCase
Section titled “strictCase”When this option is set to true, it forbids consecutive uppercase characters in camelCase and PascalCase.
Default: true
For instance, HTTPServer or aHTTPServer are not permitted for strictCase: true.
These names should be renamed to HttpServer and aHttpServer:
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "strictCase": true          }        }      }    }  }}class HTTPServer {}code-block.js:1:7 lint/style/useNamingConvention  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ Two consecutive uppercase characters are not allowed in PascalCase because strictCase is set to true.
  
  > 1 │ class HTTPServer {
      │       ^^^^^^^^^^
    2 │ }
    3 │ 
  
  ℹ If you want to use consecutive uppercase characters in PascalCase, then set the strictCase option to false.
    See the rule options for more details.
  
  ℹ Safe fix: Rename this symbol in PascalCase.
  
    1   │ - class·HTTPServer·{
      1 │ + class·HttpServer·{
    2 2 │   }
    3 3 │   
  
When strictCase is set to false, consecutive uppercase characters are allowed.
For example, HTTPServer and aHTTPServer would be considered valid then:
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "strictCase": false          }        }      }    }  }}class HTTPServer {}requireAscii
Section titled “requireAscii”When true, names must only consist of ASCII characters only,
forbidding names like café or 안녕하세요 that include non-ASCII characters.
When requireAscii is set to false, names may include non-ASCII characters.
For example, café and 안녕하세요 would be considered valid then.
Default: true
conventions
Section titled “conventions”The conventions option allows applying custom conventions.
The option takes an array of conventions.
Every convention is an object that includes an optional selector and one or more requirements (match and formats).
For example, you can enforce the use of CONSTANT_CASE for global const declarations:
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "const",                  "scope": "global"                },                "formats": [                  "CONSTANT_CASE"                ]              }            ]          }        }      }    }  }}A selector describes which declarations the convention applies to. You can select a declaration based on several criteria:
- 
kind: the kind of the declaration among:- any(default kind if the kind is unset)
- typeLike: classes, enums, type aliases, and interfaces
- class
- enum
- enumMember
- interface
- typeAlias
- function: named function declarations and expressions
- namespaceLike: TypeScript namespaces, import and export namespaces (- import * as namespace from)
- namespace: TypeScript namespaces
- importNamespace
- exportNamespace
- importAlias: default imports and aliases of named imports
- exportAlias: aliases of re-exported names
- variable: const, let, using, and var declarations
- const
- let
- var
- using
- functionParameter
- catchParameter
- indexParameter: parameters of index signatures
- typeParameter: generic type parameter
- classMember: class properties, parameter properties, methods, getters, and setters
- classProperty: class properties, including parameter properties
- classMethod
- classGetter
- classSetter
- objectLiteralMember: literal object properties, methods, getters, and setters
- objectLiteralProperty
- objectLiteralMethod
- objectLiteralGetter
- objectLiteralSetter
- typeMember: properties, methods, getters, and setters declared in type aliases and interfaces
- typeProperty
- typeMethod
- typeGetter
- typeSetter
 
- 
modifiers: an array of modifiers among:- abstract: applies to class members and classes
- private: applies to class members
- protected: applies to class members
- readonly: applies to class members and type members
- static: applies to class members
 
- 
scope: where the declaration appears. Allowed values:- any: anywhere (default value if the scope is unset)
- global: the global scope (also includes the namespace scopes)
 
For each declaration,
the conventions array is traversed in-order until a selector selects the declaration.
The requirements of the convention are so verified on the declaration.
A convention must set at least one requirement among:
- match: a regular expression that the name of the declaration must match.
- formats: the string case that the name must follow. The supported cases are:- PascalCase,- CONSTANT_CASE,- camelCase, and- snake_case.
If only formats is set, it’s checked against the name of the declaration.
In the following configuration, we require static readonly class properties to be in CONSTANT_CASE.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classProperty",                  "modifiers": [                    "static",                    "readonly"                  ]                },                "formats": [                  "CONSTANT_CASE"                ]              }            ]          }        }      }    }  }}The following code is then reported by the rule:
class C {    static readonly prop = 0;}code-block.ts:2:21 lint/style/useNamingConvention ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ℹ This readonly static class property name should be in CONSTANT_CASE.
  
    1 │ class C {
  > 2 │     static readonly prop = 0;
      │                     ^^^^
    3 │ }
    4 │ 
  
A convention can make another one useless. In the following configuration, the second convention is useless because the first one always applies to class members, including class properties. You should always place first more specific conventions.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember"                },                "formats": [                  "camelCase"                ]              },              {                "selector": {                  "kind": "classProperty"                },                "formats": [                  "camelCase",                  "CONSTANT_CASE"                ]              }            ]          }        }      }    }  }}If only match is set and the regular expression has no capturing groups,
then match is checked against the name of the declaration directly.
In the following configuration, all variable names must have a minimum of 3 characters and a maximum of 20 characters.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "variable"                },                "match": ".{3,20}"              }            ]          }        }      }    }  }}If both match and formats are set, then formats is checked against the first capture of the regular expression.
Only the first capture is tested. Other captures are ignored.
If nothing is captured, then formats is ignored.
In the following example, we require that:
- A private property starts with _and consists of at least two characters.
- The captured name (the name without the leading _) is incamelCase.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)",                "formats": [                  "camelCase"                ]              }            ]          }        }      }    }  }}If match is set and formats is unset, then the part of the name captured by the regular expression is forwarded to the next conventions of the array that selects the declaration.
The following configuration has exactly the same effect as the previous one.
The first convention applies to any private class member name.
It stipulates that the name must have a leading underscore.
The regular expression captures the part of the name without the leading underscore.
Because formats is not set, the capture is forwarded to the next convention that applies to a private class member name.
In our case, the next convention applies.
The capture is then checked against formats.
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)"                // We don't need to specify `formats` because the capture is forwarded to the next conventions.              },              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "formats": [                  "camelCase"                ]              }            ]          }        }      }    }  }}The forwarding has particularly useful to factorize some conventions. For example, the following configuration…
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)",                "formats": [                  "camelCase"                ]              },              {                "selector": {                  "kind": "classMember"                },                "formats": [                  "camelCase"                ]              }            ]          }        }      }    }  }}can be factorized to…
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)"              },              {                "selector": {                  "kind": "classMember"                },                "formats": [                  "camelCase"                ]              }            ]          }        }      }    }  }}If a declaration is not selected or if a capture is forwarded while there are no more conventions, then the declaration name is verified against the default conventions. Because the default conventions already ensure that class members are in [“camelCase”], the previous example can be simplified to:
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.+)"                // We don't need to specify `formats` because the capture is forwarded to the next conventions.              }              // default conventions            ]          }        }      }    }  }}If the capture is identical to the initial name (it is not a part of the initial name),
then, leading and trailing underscore and dollar signs are trimmed before being checked against default conventions.
In the previous example, the capture is a part of the name because _ is not included in the capture, thus, no trimming is performed.
You can reset all default conventions by adding a convention at the end of the array that accepts anything:
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              // your conventions              // ...
              // Otherwise, accept anything              {                "match": ".*"              }            ]          }        }      }    }  }}Let’s take a more complex example with the following conventions:
- A variable name is i,j, or follows the next selected convention (convention (2)).
- An identifier contains at least two characters and follow the next selected convention (the default convention).
- A privateclass member name starts with an underscore_and the name without the underscore follows the next selected convention (convention (4) for some of them, and the default convention for others).
- A static readonlyclass property name is inCONSTANT_CASE.
- A global constant is in CONSTANT_CASEand can be enclosed by double underscores or to be named_SPECIAL_.
- An interface name starts with I, except for interfaces ending withError, and is inPascalCase.
- All other names follow the default conventions
{  "linter": {    "rules": {      "style": {        "useNamingConvention": {          "options": {            "conventions": [              {                "selector": {                  "kind": "variable"                },                "match": "[ij]|(.*)"              },              {                "match": "(.{2,})"              },              {                "selector": {                  "kind": "classMember",                  "modifiers": [                    "private"                  ]                },                "match": "_(.*)"              },              {                "selector": {                  "kind": "classProperty",                  "modifiers": [                    "static",                    "readonly"                  ]                },                "formats": [                  "CONSTANT_CASE"                ]              },              {                "selector": {                  "kind": "const",                  "scope": "global"                },                "match": "__(.+)__|_SPECIAL_|(.+)",                "formats": [                  "CONSTANT_CASE"                ]              },              {                "selector": {                  "kind": "interface"                },                "match": "I(.*)|(.*?)Error",                "formats": [                  "PascalCase"                ]              }              // default conventions            ]          }        }      }    }  }}Hers some examples:
- A private class property named _is reported by the rule because it contains a single character. According to the second convention, the name should contain at least two characters.
- A variable a_variableis reported by the rule because it doesn’t respect the default convention that forbid variable names insnake_case. The variable name is first verified against the first convention. It is forwarded to the second convention, which is also respected, because it is neitherinorj. The name is captured and is forwarded to the next convention. In our case, the next convention is the default one.
Regular expression syntax
Section titled “Regular expression syntax”The match option takes a regular expression that supports the following syntaxes:
- Greedy quantifiers *,?,+,{n},{n,m},{n,},{m}
- Non-greedy quantifiers *?,??,+?,{n}?,{n,m}?,{n,}?,{m}?
- Any character matcher .
- Character classes [a-z],[xyz],[^a-z]
- Alternations |
- Capturing groups ()
- Non-capturing groups (?:)
- Case-insensitive groups (?i:)and case-sensitive groups(?-i:)
- A limited set of escaped characters including all special characters
and regular string escape characters \f,\n,\r,\t,\v. Note that you can also escape special characters using character classes. For example,\$and[$]are two valid patterns that escape$.
Related links
Section titled “Related links”Copyright (c) 2023-present Biome Developers and Contributors.