Literals
This page discusses styles for number, string, and regex literals, as well as template/symbol expressions.
Number literals
no-loss-of-precision
- Severity: error
Do not use numbers literals that don't represent what they look like. For example, 5123000000000000000000000000001
does not represent that number. Note that this rule works automatically with literal types.
no-magic-numbers
- Severity: off
You are free to use numbers as you see fit.
ts
for (let i = 0; i < groups.length; i += 2) {const x = groups[i];const y = groups[i + 1];}
ts
for (let i = 0; i < groups.length; i += 2) {const x = groups[i];const y = groups[i + 1];}
Use comments if the numbers are not self-explanatory.
no-octal
- Severity: error
- Related:
ts(1489): Decimals with leading zeros are not allowed.
Do not use legacy octal literals (011
). They are deprecated and are syntax errors in strict mode. Use 0o
instead.
prefer-numeric-literals
- Severity: error
Use 0b
and 0o
number literals instead of parseInt
with a static string.
radix
- Severity: error
- Configuration:
- Always require a radix (
"always"
)
- Always require a radix (
You should always use parseInt
with a radix. This prevents accidental behavior inconsistencies when the string starts with 0
or 0x
. If you intentionally want to accommodate many number formats, use the Number
constructor instead.
String literals
no-multi-str
- Severity: error
Do not use \
to split strings across multiple lines—it doesn't work well with indentation. Write string literals that are as long as you want.
no-nonoctal-decimal-escape
- Severity: error
Do not use \8
and \9
in string literals because they are useless and confusing. Just write 8
and 9
instead.
no-octal-escape
- Severity: error
- Related:
ts(1487): Octal escape sequences are not allowed. Use the syntax '\x3f'.
Do not use octal escapes in string literals. They are deprecated and are syntax errors in strict mode. Use \x
or \u
instead.
no-script-url
- Severity: error
Do not use javascript:
URLs. They are a form of eval
.
no-template-curly-in-string
- Severity: warning Usually, using the
${}
syntax in a string literal is a mistake. However, it's not a deadly error, so we only set it to warning.
no-useless-concat
- Severity: error
Do not use string concatenation when you can just use a single string literal. You should generally not use string concatenation to make a "multi-line string" either—just make the string literal as long as you want.
no-useless-escape
- Severity: error
Do not use \
to escape characters that do not need escaping. It's confusing and unnecessary. In regexes, these identity escapes cause syntax errors in Unicode mode (which is required).
prefer-template
- Severity: error
Use template literals instead of string concatenation. It's more readable and less error-prone. Use it everywhere — never use +
for string concatenation. This includes str1 + str2
, which should be written as `${str1}${str2}`
.
Regular expressions
Prefer concise syntax
There are many ways to represent the same regular expression. Instead of this:
ts
const rule = {test: /\.(?:js|ts|jsx|tsx)/i,};
ts
const rule = {test: /\.(?:js|ts|jsx|tsx)/i,};
Prefer this:
ts
const rule = {test: /\.[jt]sx?/i,};
ts
const rule = {test: /\.[jt]sx?/i,};
Regular expressions are not intended to be readable; they are designed for machine consumption. Convey the intent of a regular expression through test cases, not through making it verbose. Related to code for the average-intelligent.
no-control-regex
- Severity: warning
- Related:
regexp/no-control-character
Control characters are rarely used in regular expressions because they are rarely present in string literals at all. It's only set to warning so you should not fear disabling the rule where needed.
no-div-regex
- Severity: off
This is an extremely weird rule that forbids =
at the immediate beginning of a regex. We believe that the chance of one confusing /=
with /=/
is sparse, and most places have good syntax highlighting to distinguish them.
no-empty-character-class
- Severity: error
- Related:
regexp/no-empty-character-class
Empty character classes cause the regex to never match.
no-invalid-regexp
- Severity: error
- Related:
regexp/no-invalid-regexp
Write valid regular expressions. The only case where you might want to add a disable comment is when you are using novel syntax not supported by ESLint.
no-misleading-character-class
- Severity: error
- Related:
regexp/no-misleading-unicode-character
Do not write character classes that contain grapheme clusters or astral characters in general. Common ways to fix this are:
- Change character class to a disjunction
- Use the
u
flag, if you want to use astral characters - Use
\q{}
and thev
flag, if you want to use grapheme clusters
no-regex-spaces
- Severity: off
- Related:
regexp/prefer-quantifier
Although we want to use concise syntax, multiple spaces in a regex is often useful to resemble constructs that readers are familiar with.
ts
// Matches a well-formatted table rowconst match = tableRow.match(/\| Column \| Another one \|/);
ts
// Matches a well-formatted table rowconst match = tableRow.match(/\| Column \| Another one \|/);
no-useless-backreference
- Severity: error
- Related:
regexp/no-useless-backreference
Do not write backreferences that always resolve to the empty string.
prefer-named-capture-group
- Severity: warning
- Related:
regexp/prefer-named-capture-group
Named capture groups allow us to semantically identify each group. It also warns about those groups that should probably be explicitly marked as non-capturing groups.
ts
const rule = {// Is this capturing group actually useful? If I remove it, would it break// consumer code?test: /\.(jpe?g|png|webp)/i,};
ts
const rule = {// Is this capturing group actually useful? If I remove it, would it break// consumer code?test: /\.(jpe?g|png|webp)/i,};
Ultimately, this makes refactor less risky because addition of a capturing group does not shift the other indices.
diff
- const commitPattern = /(.+),(.+)/;+ const commitPattern = /(.+),(.+),(\d+)/;const date = commit.match(commitPattern)?.[1];// Oops, I need to also change `[1]` to `[2]`...
diff
- const commitPattern = /(.+),(.+)/;+ const commitPattern = /(.+),(.+),(\d+)/;const date = commit.match(commitPattern)?.[1];// Oops, I need to also change `[1]` to `[2]`...
Named capture groups isn't strongly typed in TypeScript. See microsoft/TypeScript#32098. If you access match.groups.someName
, you will get | undefined
under noUncheckedIndexAccess
, even when someName
always exists. In this case, prefer using a non-null assertion to convey developer intent.
prefer-regex-literals
- Severity: error
- Configuration:
- Do not allow using
RegExp
on a regex literal (disallowRedundantWrapping: true
)
- Do not allow using
Only use the RegExp
constructor when either the source or the flags is dynamic. Otherwise, use a regex literal. This applies to regex literals with a lot of escaping, too.
ts
// Don't write:new RegExp("https://jc-verse.github.io/js-style-guide/eslint-base/literals");// Write:/https:\/\/jc-verse\.github\.io\/js-style-guide\/eslint-base\/literals/;
ts
// Don't write:new RegExp("https://jc-verse.github.io/js-style-guide/eslint-base/literals");// Write:/https:\/\/jc-verse\.github\.io\/js-style-guide\/eslint-base\/literals/;
require-unicode-regexp
- Severity: error
- Related:
regexp/require-unicode-regexp
Always use the u
or v
flag. This does not just enable additional features; it also disables legacy features, like strict mode for regexes. See deprecated regex features.
Symbols
symbol-description
- Severity: error
Always provide a description for symbols. This is useful for debugging.