Prettier ConfigPrettier Config

arrowParens β€” parentheses around a lone arrow parameter, and the edit cost of leaving them off

The Prettier Arrow Parens option

arrowParens decides whether a single-parameter arrow function keeps its parentheses. The default always writes (x) => x; avoid writes x => x. The argument for the default is not appearance but editability β€” almost every change you make to that parameter requires the parentheses back.

Include parentheses around a sole arrow function parameter.
Prettier's own description, from the official options documentation
Default
"always"
Type
choice
CLI flag
--arrow-parens
Allowed values
alwaysavoid

What the option does

It applies to exactly one case: an arrow function with a single parameter and no destructuring, default value or type annotation. Every other arrow already requires parentheses as a matter of syntax.

// always (default)
const double = (n) => n * 2;

// avoid
const double = n => n * 2;
The only case the option affects.

Why the default is always

Because the parentheses-free form is a local optimum that you keep having to undo. Consider the ways a lone parameter commonly changes:

  • Adding a type annotation β€” (n: number) => n * 2 β€” requires parentheses.
  • Adding a default value β€” (n = 1) => n * 2 β€” requires parentheses.
  • Destructuring it β€” ({ id }) => id β€” requires parentheses.
  • Adding a second parameter requires parentheses.
  • Adding a leading comment or a decorator requires parentheses.

Each of those edits therefore touches the parameter and its punctuation, producing a slightly noisier diff than the change deserves. always pays two characters up front so that none of those edits ever costs more than the change itself.

The effect is strongest in TypeScript, where adding a type to a callback parameter is a routine edit rather than a rare one.

The case for avoid

avoid reads better in dense functional code. A chain of small transformations β€” items.map(x => x.id).filter(id => id != null) β€” is genuinely lighter without the parentheses, and if your codebase is full of one-line callbacks that argument carries real weight.

It is also the older convention: a lot of JavaScript written between roughly 2016 and 2019 omits them, so matching it can make a codebase feel consistent with its own history.

Common mistakes

  • Expecting avoid to strip parentheses from every arrow. It only affects the single-plain-parameter case; all others are syntactically required.
  • Choosing avoid in a TypeScript codebase and then fighting it every time a parameter needs a type.
  • Leaving ESLint’s arrow-parens rule enabled alongside Prettier, which produces a rule that can never be satisfied.

The default changed in Prettier 2.0

Prettier 1.x defaulted to avoid, so a great deal of code written in that era has bare single parameters. Prettier 2.0 changed the default to always, and the reasoning given was precisely the edit-cost argument above: the parentheses-free form has to be undone by most of the changes people actually make to a parameter.

If you are upgrading a project that has been pinned to Prettier 1 and you see every short arrow function change, this is the cause. Setting "arrowParens": "avoid" reproduces the old output exactly and lets you take the version bump without the reformat.

Why TypeScript pushes harder toward always

In JavaScript a callback parameter usually stays bare for its whole life. In TypeScript it frequently does not: an implicit any gets flagged, an inference fails, a signature changes, and a type annotation appears. Every one of those edits requires the parentheses.

With strict and noImplicitAny enabled β€” which is the default for new TypeScript projects β€” the compiler actively pushes you toward annotating parameters that are not contextually typed. avoid then means a steady trickle of diffs where the punctuation changes alongside the type.

// before
const byId = (u) => u.id;

// after adding a type
const byId = (u: User) => u.id;
The edit that keeps forcing parentheses back.

Use it in .prettierrc

Drop arrowParens into your Prettier config file:

{
  "arrowParens": "always"
}
Try it in the generator

Worked examples

The same code formatted with each value of arrowParens.

arrowParens: always

const user = {
  name: "Ada",
  "user-id": 7,
  roles: ["admin", "editor"],
  active: true,
};
const greet = (name) => `Hello ${name}`;
const label = user.active
  ? "active member of the team"
  : "inactive member of the team";
export function summarize(items) {
  return items
    .filter((i) => i.active)
    .map((i) => i.name)
    .join(", ");
}

arrowParens: avoid

const user = {
  name: "Ada",
  "user-id": 7,
  roles: ["admin", "editor"],
  active: true,
};
const greet = name => `Hello ${name}`;
const label = user.active
  ? "active member of the team"
  : "inactive member of the team";
export function summarize(items) {
  return items
    .filter(i => i.active)
    .map(i => i.name)
    .join(", ");
}

Allowed values

always
Always include parens. Example: `(x) => x`
avoid
Omit parens when possible. Example: `x => x`

Common questions

Why does Prettier keep the parentheses even with avoid set?
Because that particular arrow is not the single-plain-parameter case. Type annotations, default values, destructuring, rest parameters and multiple parameters all require parentheses as syntax.
Which should a TypeScript project choose?
always is the better fit. Annotating a callback parameter is a routine edit in TypeScript, and each one would otherwise have to add the parentheses back.

Other JavaScript options

Generated from Prettier 3.9.6.