Returning Objects from JS Arrow Functions Guide

Arrow functions need parentheses around the curly braces to return an object literal. Learn why () => ({ key: value }) works and () => { key: value } does not.

5 min read

Arrow functions have a convenient implicit return: when the body is a single expression, you can drop the return keyword and the curly braces entirely, letting the expression's value become the return value automatically.

javascriptjavascript
const add = (a, b) => a + b; // Implicitly returns a + b

But this convenience creates a problem when you want to return an object literal. An object literal also uses curly braces, and JavaScript cannot tell whether you mean a function body or an object.

The Problem

Writing an arrow function that tries to shortcut straight to an object literal looks reasonable, but it silently fails. This version does not work the way it appears to:

javascriptjavascript
const createUser = (name) => {
  name: name,
  age: 30,
};
 
console.log(createUser("Alex")); // undefined

The function returns undefined. Why? JavaScript sees the opening curly brace after the arrow and assumes it is a function block body.

Inside that block, name: is parsed as a JavaScript label, similar to a break target, not an object key. There is no return statement, so the function returns undefined.

The Solution: Wrap in Parentheses

Add parentheses around the object literal:

javascriptjavascript
const createUser = (name) => ({
  name: name,
  age: 30,
});
 
console.log(createUser("Alex")); // { name: "Alex", age: 30 }

The parentheses tell the parser: "this is an expression, not a block body." The curly braces inside the parentheses are unambiguously an object literal.

The Rule

When the token after the arrow is an opening curly brace, JavaScript assumes a block body. To return an object literal, wrap it in parentheses:

javascriptjavascript
// Block body (needs explicit return)
const fn1 = () => {
  return { key: "value" };
};
 
// Expression body returning an object (wrap in parentheses)
const fn2 = () => ({ key: "value" });

Both work. The second is shorter. Choose whichever is clearer in context.

Common Patterns

The parenthesized-object pattern shows up constantly in real code, most often wherever a short callback needs to build a new object from its input.

In Array Methods

Transforming an array of objects into a new shape is one of the most common places this pattern appears:

javascriptjavascript
const users = [
  { first: "Alex", last: "Chen" },
  { first: "Sara", last: "Khan" },
];
 
const names = users.map(user => ({
  full: `${user.first} ${user.last}`,
  initials: `${user.first[0]}${user.last[0]}`,
}));

Each call to the callback builds and returns one new object, so map collects them into a new array of results:

javascriptjavascript
console.log(names);
// [
//   { full: "Alex Chen", initials: "AC" },
//   { full: "Sara Khan", initials: "SK" },
// ]

Without the parentheses, map would return an array of undefined values instead of the objects shown above.

In React Components

The same pattern appears whenever a list of items needs to become a list of props objects, such as before rendering each one as a component:

javascriptjavascript
const items = ["a", "b", "c"];
const components = items.map((item, index) => ({
  id: index,
  label: item,
}));

With Computed Property Keys

The rule applies the same way even when a property name is computed at runtime instead of written literally:

javascriptjavascript
const prop = "score";
 
const createStats = (value) => ({
  [prop]: value,
  timestamp: Date.now(),
});
 
console.log(createStats(95)); // { score: 95, timestamp: 1747200000000 }

With Spread Operator

Merging default values with overrides is another common case, and it needs the same parentheses since the result is still an object literal:

javascriptjavascript
const defaults = { theme: "light", fontSize: 14 };
 
const withOverrides = (overrides) => ({
  ...defaults,
  ...overrides,
});
 
console.log(withOverrides({ theme: "dark" }));
// { theme: "dark", fontSize: 14 }

When You Do NOT Need Parentheses

If the arrow function has a block body with an explicit return statement, no parentheses are needed around the object:

javascriptjavascript
const createUser = (name) => {
  const id = crypto.randomUUID();
  return {
    name,
    id,
    createdAt: new Date(),
  };
};

The return keyword makes the intent explicit, so there is no ambiguity. Use this form when you need to compute intermediate values before building the object.

Comparison

SyntaxWhat it does
() => { name: "Alex" }Block body with a label. Returns undefined.
() => ({ name: "Alex" })Expression body. Returns { name: "Alex" }.
() => { return { name: "Alex" }; }Block body with explicit return. Returns { name: "Alex" }.

Why Only Arrow Functions?

Regular functions do not have this problem because the function keyword always precedes the body:

javascriptjavascript
// No ambiguity: function keyword already established the context
const createUser = function(name) {
  return { name, age: 30 };
};

The ambiguity is unique to arrow functions because the arrow can be followed by either a single expression or a block body. For more on arrow function syntax, see JavaScript Arrow Functions: A Complete ES6 Guide. For when not to use arrows, see When to Avoid Using Arrow Functions in JavaScript.

Rune AI

Rune AI

Key Insights

  • Wrap object literals in parentheses to return them from arrow functions: () => ({ key: value }).
  • Without the parentheses, the braces are parsed as a block body, not an object literal.
  • This only applies to arrow functions with expression bodies. Regular functions do not have this ambiguity.
  • The pattern is common in map, filter chains, and React components.
  • If the object has computed keys or spread properties, the same rule applies: wrap in parentheses.
RunePowered by Rune AI

Frequently Asked Questions

Why does () => { name: 'Alex' } return undefined?

Because the curly braces are parsed as a function block body, not an object literal. Inside the block, name: is interpreted as a label, not a property key. Since there is no return statement, the function returns undefined.

Does this only apply to arrow functions?

Yes. Regular function expressions and declarations have the function keyword before the body, so the parser always knows the braces are a block body. The ambiguity only exists with arrow functions because the => can be followed by either an expression or a block.

Can I use this pattern in array methods like map?

Yes, and it is very common: users.map(user => ({ name: user.name, id: user.id })). The parentheses make it clear you are returning an object, not writing a block body.

Conclusion

Returning an object from an arrow function requires one small trick: wrap the curly braces in parentheses. () => ({ key: value }). Forget the parentheses and JavaScript sees a block body with a label, not an object literal. This is one of the most common arrow function mistakes, and now you know exactly why it happens and how to avoid it.